Le sous-processus Python readlines() Problème de blocage
La diffusion en continu d'un fichier et l'impression de la sortie ligne par ligne peuvent être réalisées en utilisant diverses méthodes. Cependant, l'utilisation d'un sous-processus avec readlines() peut entraîner des problèmes de blocage.
Considérez le script Python "main.py" conçu pour diffuser un fichier Ruby "ruby_sleep.rb" et imprimer sa sortie.
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")
L'exécution de ce script diffuse la sortie Ruby sous la forme attendu, mais la méthode readline() se bloque indéfiniment, ce qui fait que la chaîne « Cette ligne n'est jamais atteinte » n'est jamais imprimée.
Diverses solutions ont été proposées pour résoudre ce problème de blocage. :
Stdbuf permet la mise en mémoire tampon de ligne en mode non interactif.
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()
Pexpect peut être utilisé pour un contrôle basé sur la ligne.
import pexpect pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
PTY permet de fournir un terminal pour activer la mise en mémoire tampon de ligne côté Ruby.
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!")
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!