Heim  >  Artikel  >  Backend-Entwicklung  >  Warum bleibt meine Python-Datei „subprocess.readline' hängen, wenn sie aus einem kontinuierlich schreibenden C-Programm liest?

Warum bleibt meine Python-Datei „subprocess.readline' hängen, wenn sie aus einem kontinuierlich schreibenden C-Programm liest?

Linda Hamilton
Linda HamiltonOriginal
2024-11-19 16:09:03540Durchsuche

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

Python-Unterprozess readline hängt bei „for line in iter“

Problem

Beim Versuch, die Ausgabe eines C-Programms zu lesen, nämlich „2000 ,“ aus einem Python-Skript, das einen Unterprozess verwendet, hängt das Skript an der „for“-Zeile in iter(process.stdout.readline, '')" Linie. Dies geschieht, obwohl das C-Programm ständig „2000“ ausgibt und nie einen Endzustand erreicht.

Lösung

Das Problem ist auf ein Problem mit der Blockpufferung zurückzuführen. Standardmäßig ist stdout in C-Programmen, die über Pipes ausgeführt werden (z. B. bei Verwendung von subprocess.Popen), blockgepuffert. Dies bedeutet, dass Daten erst in die Pipe geleert werden, wenn der Puffer voll ist oder explizit geleert wird.

Option 1: C-Programm direkt ändern

Um das Problem zu beheben, müssen Sie kann erzwingen, dass stdout im C-Programm zeilengepuffert wird:

#include <stdio.h>

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

Option 2: Verwenden Sie stdbuf Dienstprogramm

Alternativ können Sie das Dienstprogramm stdbuf verwenden, um den Puffertyp zu ändern, ohne die C-Programmquelle zu ändern:

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()

Option 3: Pseudo-TTY verwenden

Ein anderer Ansatz besteht darin, ein Pseudo-TTY zu verwenden, um dem C-Programm vorzutäuschen, dass es läuft interaktiv:

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

Option 4: Verwenden Sie pexpect

Pexpect bietet eine übergeordnete Schnittstelle, die die Pseudo-TTY-Verarbeitung vereinfacht:

import pexpect

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

Das obige ist der detaillierte Inhalt vonWarum bleibt meine Python-Datei „subprocess.readline' hängen, wenn sie aus einem kontinuierlich schreibenden C-Programm liest?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn