J'utilise une bibliothèque Python qui fait quelque chose avec un objet
do_something(my_object)
et le change. Ce faisant, certaines statistiques sont imprimées sur stdout, et j'aimerais bien maîtriser ces informations. La bonne solution serait de changer do_something()
pour renvoyer les informations pertinentes,
out = do_something(my_object)
mais il faudra un certain temps avant que les développeurs de do_something()
ne parviennent à ce problème. En guise de solution de contournement, j'ai pensé à analyser tout ce que do_something()
écrit sur stdout.
Comment puis-je capturer la sortie stdout entre deux points du code, par exemple,
start_capturing()
do_something(my_object)
out = end_capturing()
?
Essayez ce gestionnaire de contexte:
# import StringIO for Python 2 or 3
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
import sys
class Capturing(list):
def __enter__(self):
self._stdout = sys.stdout
sys.stdout = self._stringio = StringIO()
return self
def __exit__(self, *args):
self.extend(self._stringio.getvalue().splitlines())
del self._stringio # free up some memory
sys.stdout = self._stdout
Usage:
with Capturing() as output:
do_something(my_object)
output
est maintenant une liste contenant les lignes imprimées par l'appel de fonction.
Utilisation avancée:
Ce qui n’est peut-être pas évident, c’est que cela peut être fait plus d’une fois et que les résultats sont concaténés:
with Capturing() as output:
print 'hello world'
print 'displays on screen'
with Capturing(output) as output: # note the constructor argument
print 'hello world2'
print 'done'
print 'output:', output
Sortie:
displays on screen
done
output: ['hello world', 'hello world2']
Update : Ils ont ajouté redirect_stdout()
à contextlib
in Python 3.4 (avec redirect_stderr()
). Vous pouvez donc utiliser io.StringIO
Avec cela pour obtenir un résultat similaire (bien que Capturing
soit une liste et un contexte gestionnaire est sans doute plus pratique).
Dans python> = 3.4, la contextlib contient un redirect_stdout
décorateur. Il peut être utilisé pour répondre à votre question comme suit:
import io
from contextlib import redirect_stdout
f = io.StringIO()
with redirect_stdout(f):
do_something(my_object)
out = f.getvalue()
De les docs :
Gestionnaire de contexte pour la redirection temporaire de sys.stdout vers un autre fichier ou un objet de type fichier.
Cet outil ajoute de la flexibilité aux fonctions ou aux classes existantes dont la sortie est câblée sur stdout.
Par exemple, la sortie de help () est normalement envoyée à sys.stdout. Vous pouvez capturer cette sortie dans une chaîne en redirigeant la sortie vers un objet io.StringIO:
f = io.StringIO() with redirect_stdout(f): help(pow) s = f.getvalue()
Pour envoyer la sortie de help () dans un fichier sur le disque, redirigez la sortie vers un fichier normal:
with open('help.txt', 'w') as f: with redirect_stdout(f): help(pow)
Pour envoyer la sortie de help () à sys.stderr:
with redirect_stdout(sys.stderr): help(pow)
Notez que l'effet secondaire global sur sys.stdout signifie que ce gestionnaire de contexte ne convient pas pour une utilisation dans le code de bibliothèque et dans la plupart des applications à threads. Cela n'a également aucun effet sur la sortie des sous-processus. Cependant, cela reste une approche utile pour de nombreux scripts d’utilitaires.
Ce gestionnaire de contexte est réentrant.