Heim >Backend-Entwicklung >Python-Tutorial >Warum bleibt Pythons „subprocess.Popen' mit „readlines()' hängen und wie kann ich das beheben?

Warum bleibt Pythons „subprocess.Popen' mit „readlines()' hängen und wie kann ich das beheben?

DDD
DDDOriginal
2024-12-03 10:37:10147Durchsuche

Why Does Python's `subprocess.Popen` with `readlines()` Hang, and How Can I Fix It?

Python-Unterprozess readlines() hängt Problem

Einführung

Das Streamen einer Datei und das zeilenweise Drucken der Ausgabe können erreicht werden mit verschiedenen Methoden. Die Verwendung eines Unterprozesses mit readlines() kann jedoch zu Problemen mit dem Aufhängen führen.

Das Python-Skript

Betrachten Sie das Python-Skript „main.py“, das zum Streamen einer Ruby-Datei „ruby_sleep.rb“ und entwickelt wurde druckt seine Ausgabe.

import pty
import os
from subprocess import Popen, PIPE, STDOUT

file_path = '/path/to/ruby_sleep.rb'
command = ' '.join(["ruby", file_path])

master, slave = pty.openpty()
proc = Popen(command, bufsize=0, shell=True, stdout=slave, stderr=slave, close_fds=True)     
stdout = os.fdopen(master, 'r', 0)

while proc.poll() is None:
    data = stdout.readline()
    if data != "":
        print(data)
    else:
        break

print("This line is never reached")

Das Problem und die Beobachtungen

Durch die Ausführung dieses Skripts wird die Ruby-Ausgabe gestreamt wie erwartet, aber die readline()-Methode bleibt auf unbestimmte Zeit hängen, was dazu führt, dass die Zeichenfolge „Diese Zeile wird nie erreicht“ nie gedruckt wird.

Lösungsansätze

Es wurden verschiedene Lösungen vorgeschlagen, um dieses Problem zu beheben Problem:

1. Die Verwendung von Stdbuf

Stdbuf ermöglicht die Zeilenpufferung im nicht-interaktiven Modus.

from subprocess import Popen, PIPE, STDOUT

proc = Popen(['stdbuf', '-oL', 'ruby', 'ruby_sleep.rb'],
             bufsize=1, stdout=PIPE, stderr=STDOUT, close_fds=True)
for line in iter(proc.stdout.readline, b''):
    print line,
proc.stdout.close()
proc.wait()

2. Verwendung von Pexpect

Pexpect kann zur zeilenbasierten Steuerung verwendet werden.

import pexpect

pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)

3. Die Verwendung von PTY

PTY ermöglicht die Bereitstellung eines TTY, um die Zeilenpufferung auf der Ruby-Seite zu ermöglichen.

import os
import pty
from subprocess import Popen, STDOUT

master_fd, slave_fd = pty.openpty()
proc = Popen(['ruby', 'ruby_sleep.rb'],
             stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, close_fds=True)
os.close(slave_fd)
while 1:
    try:
        data = os.read(master_fd, 512)
    except OSError as e:
        if e.errno != errno.EIO:
            raise
        break # EIO means EOF on some systems
    else:
        if not data: # EOF
            break
        print('got ' + repr(data))
finally:
    os.close(master_fd)
    if proc.poll() is None:
        proc.kill()
    proc.wait()
    print("This is reached!")

Das obige ist der detaillierte Inhalt vonWarum bleibt Pythons „subprocess.Popen' mit „readlines()' hängen und wie kann ich das beheben?. 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