Maison >développement back-end >Tutoriel Python >Pourquoi « subprocess.readlines() » de Python se bloque-t-il lors de la diffusion de la sortie Ruby et comment puis-je y remédier ?

Pourquoi « subprocess.readlines() » de Python se bloque-t-il lors de la diffusion de la sortie Ruby et comment puis-je y remédier ?

Patricia Arquette
Patricia Arquetteoriginal
2024-12-05 16:32:11839parcourir

Why Does Python's `subprocess.readlines()` Hang When Streaming Ruby Output, and How Can I Fix It?

Python Subprocess Readlines() se bloque

Énoncé du problème :

Lors de la tentative de diffusion d'un Fichier Ruby ligne par ligne en Python à l'aide du module subprocess, l'appel readlines() se bloque indéfiniment, empêchant davantage exécution.

Cause :

Ce problème peut survenir lors de l'utilisation du module pty sur un système d'exploitation non-Linux pour simuler un pseudo-terminal. pty est une bibliothèque spécifique à Linux et son comportement sur d'autres systèmes n'est pas garanti.

Solutions :

1. Utilisez Pexpect :

Pexpect est une bibliothèque multiplateforme conçue pour automatiser les applications interactives. Il fournit une interface de haut niveau pour envoyer et recevoir des données sur un pseudo-terminal.

import pexpect

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

2. Utiliser Stdbuf :

Stdbuf peut être utilisé pour activer la mise en mémoire tampon de ligne en mode non interactif, permettant ainsi de vider la sortie sur chaque ligne.

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

3. Utilisez Pty depuis la bibliothèque standard (pour Linux) :

import errno
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!")

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn