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
Freigeben: 2024-12-03 10:37:10
Original
142 Leute haben es durchsucht

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")
Nach dem Login kopieren

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()
Nach dem Login kopieren

2. Verwendung von Pexpect

Pexpect kann zur zeilenbasierten Steuerung verwendet werden.

import pexpect

pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
Nach dem Login kopieren

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!")
Nach dem Login kopieren

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!

Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage