


Warum bleibt „subprocess.Popen' mit „readline()' hängen, wenn aus einem Ruby-Skript gelesen wird, und wie kann das behoben werden?
Python-Subprozess readlines() hängt
Problem:
Beim Lesen der Ausgabe eines Ruby-Skripts mit subprocess.Popen und readline() im Streaming-Modus, readline() bleibt auf unbestimmte Zeit und nie hängen kehrt zurück.
Hintergrund:
Das Ziel besteht darin, die Ausgabe einer Ruby-Datei Zeile für Zeile zu streamen und sie zu drucken, ohne die gesamte Ausgabe zu puffern.
from subprocess import Popen, PIPE, STDOUT import pty import os file_path = '/Users/luciano/Desktop/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 is never reached!")
Das ruby_sleep.rb-Skript gibt eine einfache Nachricht mit einer Dauer von 2 Sekunden aus Verzögerung:
puts "hello" sleep 2 puts "goodbye!"
Grundursache:
readline() bleibt hängen, da das Ruby-Skript Daten ohne Abschlusszeilen (d. h. ohne Zeilenumbrüche) ausgibt. Dies führt dazu, dass readline() unbegrenzt darauf wartet, dass eine neue Zeile die Zeile vervollständigt.
Lösungen:
Je nach Plattformverfügbarkeit gibt es mehrere Lösungen:
-
Für Linux:
Verwenden Sie pty aus der Standardbibliothek, um ein Pseudo-Terminal (tty) zu öffnen und die Zeilenpufferung auf der Ruby-Seite zu aktivieren, um sicherzustellen, dass jede Zeile mit einer neuen Zeile abgeschlossen wird.
import os import pty from subprocess import Popen, STDOUT master_fd, slave_fd = pty.openpty() # provide tty to enable # line-buffering on ruby's side proc = Popen(['ruby', 'ruby_sleep.rb'], stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, close_fds=True) os.close(slave_fd) try: 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 -
Für Linux-basierte Plattformen:
Verwenden Sie pty aus der Standardbibliothek und wählen Sie aus, dass der Master-Dateideskriptor auf Aktivität überwacht werden soll, um sicherzustellen, dass die Daten vorhanden sind Nicht blockierend lesen.
import os import pty import select from subprocess import Popen, STDOUT master_fd, slave_fd = pty.openpty() # provide tty to enable # line-buffering on ruby's side proc = Popen(['ruby', 'ruby_sleep.rb'], stdout=slave_fd, stderr=STDOUT, close_fds=True) timeout = .04 # seconds while 1: ready, _, _ = select.select([master_fd], [], [], timeout) if ready: data = os.read(master_fd, 512) if not data: break print("got " + repr(data)) elif proc.poll() is not None: # select timeout assert not select.select([master_fd], [], [], 0)[0] # detect race condition break # proc exited os.close(slave_fd) # can't do it sooner: it leads to errno.EIO error os.close(master_fd) proc.wait() print("This is reached!")
Nach dem Login kopieren -
Plattformübergreifende Option:
Verwenden Sie stdbuf, um die Zeilenpufferung im nicht interaktiven Modus zu aktivieren 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
Diese Lösungen ermöglichen alle eine Zeilenpufferung auf der Ruby-Seite, um sicherzustellen, dass jede Zeile mit einem Zeilenumbruch abgeschlossen wird, damit readline() korrekt funktioniert.
Das obige ist der detaillierte Inhalt vonWarum bleibt „subprocess.Popen' mit „readline()' hängen, wenn aus einem Ruby-Skript gelesen wird, und wie kann das behoben werden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen

Wie kann man nicht erkannt werden, wenn Sie Fiddlereverywhere für Man-in-the-Middle-Lesungen verwenden, wenn Sie FiddLereverywhere verwenden ...

Fastapi ...

Verwenden Sie Python im Linux -Terminal ...

Wie lehre ich innerhalb von 10 Stunden die Grundlagen für Computer -Anfänger für Programmierungen? Wenn Sie nur 10 Stunden Zeit haben, um Computer -Anfänger zu unterrichten, was Sie mit Programmierkenntnissen unterrichten möchten, was würden Sie dann beibringen ...

Über Pythonasyncio ...

Verständnis der Anti-Crawling-Strategie von Investing.com Viele Menschen versuchen oft, Nachrichten von Investing.com (https://cn.investing.com/news/latest-news) zu kriechen ...

Laden Sie die Gurkendatei in Python 3.6 Umgebungsfehler: ModulenotFoundError: Nomodulenamed ...

Diskussion über die Gründe, warum Pipeline -Dateien beim Lernen und Verwendung von Scapy -Crawlern für anhaltende Datenspeicher nicht geschrieben werden können, können Sie auf Pipeline -Dateien begegnen ...
