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
Libérer: 2024-12-05 16:32:11
original
820 Les gens l'ont consulté

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)
Copier après la connexion

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()
Copier après la connexion

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!")
Copier après la connexion

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal