124 votes

Capturer la sortie standard d'un script en Python

supposons qu'il y ait un script faisant quelque chose comme ceci:

 # module writer.py
import sys

def write():
    sys.stdout.write("foobar")
 

Supposons maintenant que je veuille capturer la sortie de la fonction write et la stocker dans une variable pour un traitement ultérieur. La solution naïve était:

 # module mymodule.py
from writer import write

out = write()
print out.upper()
 

Mais ça ne marche pas. Je propose une autre solution et cela fonctionne, mais s'il vous plaît, laissez-moi savoir s'il existe un meilleur moyen de résoudre le problème. Merci

 import sys
from cStringIO import StringIO

# setup the environment
backup = sys.stdout

# ####
sys.stdout = StringIO()     # capture output
write()
out = sys.stdout.getvalue() # release output
# ####

sys.stdout.close()  # close the stream 
sys.stdout = backup # restore original stdout

print out.upper()   # post processing
 

56voto

Matthew Flaschen Points 131723

Définir stdout est un moyen raisonnable de le faire. Une autre consiste à l'exécuter en tant que processus différent:

 import subprocess

proc = subprocess.Popen(["python", "-c", "import writer; writer.write()"], stdout=subprocess.PIPE)
out = proc.communicate()[0]
print out.upper()
 

52voto

user1200039 Points 201

Voici une version de gestionnaire de contexte de votre code. Cela donne une liste de deux valeurs; le premier est stdout, le second est stderr.

 import contextlib
@contextlib.contextmanager
def capture():
    import sys
    from cStringIO import StringIO
    oldout,olderr = sys.stdout, sys.stderr
    try:
        out=[StringIO(), StringIO()]
        sys.stdout,sys.stderr = out
        yield out
    finally:
        sys.stdout,sys.stderr = oldout, olderr
        out[0] = out[0].getvalue()
        out[1] = out[1].getvalue()

with capture() as out:
    print 'hi'
 

10voto

Guandalino Points 3287

Ceci est la contrepartie décoratrice de mon code original.

writer.py reste le même:

 import sys

def write():
    sys.stdout.write("foobar")
 

mymodule.py légèrement modifié:

 from writer import write as _write
from decorators import capture

@capture
def write():
    return _write()

out = write()
# out post processing...
 

Et voici le décorateur:

 def capture(f):
    """
    Decorator to capture standard output
    """
    def captured():
        import sys
        from cStringIO import StringIO

        # setup the environment
        backup = sys.stdout

        try:
            sys.stdout = StringIO()     # capture output
            f()
            out = sys.stdout.getvalue() # release output
        finally:
            sys.stdout.close()  # close the stream 
            sys.stdout = backup # restore original stdout

        return out # captured output wrapped in a string

    return captured
 

5voto

Jeremiah Willcock Points 14674

La question ici (l'exemple de la redirection de la sortie, et non de la partie tee ) utilise os.dup2 pour rediriger un flux au niveau du système d'exploitation. C'est bien, car cela s'appliquera également aux commandes que vous créez à partir de votre programme.

4voto

Alex Fedorov Points 119

Je pense que vous devriez regarder ces quatre objets:

 from test.test_support import captured_stdout, captured_output, \
    captured_stderr, captured_stdin
 

Exemple:

 from writer import write

with captured_stdout() as stdout:
    write()
print stdout.getvalue().upper()
 

UPD: Comme Eric l'a dit dans un commentaire, il ne faut pas les utiliser directement, alors je l'ai copié et collé.

 # Code from test.test_support:
import contextlib
import sys

@contextlib.contextmanager
def captured_output(stream_name):
    """Return a context manager used by captured_stdout and captured_stdin
    that temporarily replaces the sys stream *stream_name* with a StringIO."""
    import StringIO
    orig_stdout = getattr(sys, stream_name)
    setattr(sys, stream_name, StringIO.StringIO())
    try:
        yield getattr(sys, stream_name)
    finally:
        setattr(sys, stream_name, orig_stdout)

def captured_stdout():
    """Capture the output of sys.stdout:

       with captured_stdout() as s:
           print "hello"
       self.assertEqual(s.getvalue(), "hello")
    """
    return captured_output("stdout")

def captured_stderr():
    return captured_output("stderr")

def captured_stdin():
    return captured_output("stdin")
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X