Rumah >pembangunan bahagian belakang >Tutorial Python >Mengapa Python `subprocess.readline` Saya Bergantung Semasa Membaca daripada Program C Menulis Berterusan?

Mengapa Python `subprocess.readline` Saya Bergantung Semasa Membaca daripada Program C Menulis Berterusan?

Linda Hamilton
Linda Hamiltonasal
2024-11-19 16:09:03597semak imbas

Why Does My Python `subprocess.readline` Hang When Reading from a Continuously Writing C Program?

Python subprocess readline Digantung pada "for line in iter"

Isu

Apabila cuba membaca output program C, iaitu "2000 ," daripada skrip Python menggunakan subproses, skrip digantung pada "for line in iter(process.stdout.readline, '')" baris. Ini berlaku walaupun program C terus mencetak "2000" dan tidak pernah mencapai keadaan tamat.

Penyelesaian

Masalahnya berpunca daripada isu penimbalan blok. Secara lalai, stdout dalam program C yang berjalan melalui paip (cth., apabila menggunakansubprocess.Popen) ditimbalkan blok. Ini bermakna data tidak disalurkan ke paip sehingga penimbal penuh atau disiram secara eksplisit.

Pilihan 1: Ubah Suai Program C Secara Terus

Untuk menyelesaikan isu, anda boleh memaksa stdout untuk ditimbalkan talian dalam program C:

#include <stdio.h>

int main() {
    setvbuf(stdout, (char *) NULL, _IOLBF, 0); // Make line buffered stdout
    while (1) {
        printf("2000\n");
        sleep(1);
    }
    return 0;
}

Pilihan 2: Gunakan stdbuf Utility

Sebagai alternatif, anda boleh menggunakan utiliti stdbuf untuk menukar jenis penimbal tanpa mengubah suai sumber program C:

from subprocess import Popen, PIPE

process = Popen(["stdbuf", "-oL", "./main"], stdout=PIPE, bufsize=1)
for line in iter(process.stdout.readline, b''):
    print(line)
process.communicate()

Pilihan 3: Gunakan Pseudo-TTY

Pendekatan lain melibatkan penggunaan pseudo-TTY untuk menipu atur cara C untuk berfikir ia berjalan secara interaktif:

import os
import pty
import sys
from select import select
from subprocess import Popen, STDOUT

master_fd, slave_fd = pty.openpty()
process = Popen("./main", stdin=slave_fd, stdout=slave_fd, stderr=STDOUT,
                bufsize=0, close_fds=True)
timeout = .1
with os.fdopen(master_fd, 'r+b', 0) as master:
    input_fds = [master, sys.stdin]
    while True:
        fds = select(input_fds, [], [], timeout)[0]
        # Handle subprocess output and user input here

Pilihan 4: Gunakan peexpect

Pexpect menawarkan antara muka peringkat lebih tinggi yang memudahkan pengendalian pseudo-TTY:

import pexpect

child = pexpect.spawn("./.main")
for line in child:
    print(line)
child.close()

Atas ialah kandungan terperinci Mengapa Python `subprocess.readline` Saya Bergantung Semasa Membaca daripada Program C Menulis Berterusan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn