Question

Si c'est mon sous-processus :

import time, sys
for i in range(200):
    sys.stdout.write( 'reading %i\n'%i )
    time.sleep(.02)

Et voici le script contrôlant et modifiant la sortie du sous-processus :

import subprocess, time, sys

print 'starting'

proc = subprocess.Popen(
    'c:/test_apps/testcr.py',
    shell=True,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE  )

print 'process created'

while True:
    #next_line = proc.communicate()[0]
    next_line = proc.stdout.readline()
    if next_line == '' and proc.poll() != None:
        break
    sys.stdout.write(next_line)
    sys.stdout.flush()

print 'done'

Pourquoi est-ce readline et communicate attendre que le processus soit terminé ?Existe-t-il un moyen simple de transmettre (et de modifier) ​​la sortie standard du sous-processus en temps réel ?

BTW, j'ai vu ce, mais je n'ai pas besoin des fonctionnalités de journalisation (et je n'ai pas pris la peine d'en comprendre grand-chose).

Je suis sous Windows XP.

Était-ce utile?

La solution

Comme Charles l'a déjà mentionné, le problème est la mise en mémoire tampon.J'ai rencontré un problème similaire lors de l'écriture de certains modules pour SNMPd et je l'ai résolu en remplaçant stdout par une version à vidage automatique.

J'ai utilisé le code suivant, inspiré de certains articles sur ActiveState :

class FlushFile(object):
    """Write-only flushing wrapper for file-type objects."""
    def __init__(self, f):
        self.f = f
    def write(self, x):
        self.f.write(x)
        self.f.flush()

# Replace stdout with an automatically flushing version
sys.stdout = FlushFile(sys.__stdout__)

Autres conseils

La sortie du processus est mise en mémoire tampon.Sur davantage de systèmes d'exploitation UNIXy (ou Cygwin), le je m'attends Un module est disponible, qui récite toutes les incantations nécessaires pour éviter les problèmes liés à la mise en mémoire tampon.Cependant, ces incantations nécessitent un travail module pty, qui n'est pas disponible sur les versions Python win32 natives (non cygwin).

Dans le cas d'exemple où vous contrôlez le sous-processus, vous pouvez simplement le faire appeler sys.stdout.flush() si nécessaire - mais pour les sous-processus arbitraires, cette option n'est pas disponible.

Voir également la question "Pourquoi ne pas simplement utiliser un tube (popen()) ?" dans la FAQ pexpect.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top