Supprimer stdout / stderr imprimer à partir de fonctions Python
J'ai un script Python qui est l'utilisation de certaines fermé la boîte de fonctions Python (c'est à dire je ne peux pas modifier ces fonctions) fourni par mon employeur. Quand j'ai appeler ces fonctions, ils sont d'impression sortie de mon terminal linux que je voudrais supprimer. J'ai essayé de rediriger stdout /stderr via;
orig_out = sys.stdout
sys.stdout = StringIO()
rogue_function()
sys.stdout = orig_out
mais cela ne parvient pas à attraper la sortie. Je pense que les fonctions, je vais appeler via-Python (rogue_function() à partir de ci-dessus) sont vraiment des wrappers pour compilé en code C, qui sont en train de faire l'impression.
Personne ne sait d'une manière que je peux faire un "profond-capture" de toute impression remis à stdout /stderr par une fonction (et tous les sous-fonctions que les appels de fonction)?
Mise à JOUR:
J'ai fini par prendre la méthode décrite dans la réponse sélectionnée ci-dessous et l'écriture d'un gestionnaire de contexte de suppression des stdout et stderr:
# Define a context manager to suppress stdout and stderr.
class suppress_stdout_stderr(object):
'''
A context manager for doing a "deep suppression" of stdout and stderr in
Python, i.e. will suppress all print, even if the print originates in a
compiled C/Fortran sub-function.
This will not suppress raised exceptions, since exceptions are printed
to stderr just before a script exits, and after the context manager has
exited (at least, I think that is why it lets exceptions through).
'''
def __init__(self):
# Open a pair of null files
self.null_fds = [os.open(os.devnull,os.O_RDWR) for x in range(2)]
# Save the actual stdout (1) and stderr (2) file descriptors.
self.save_fds = [os.dup(1), os.dup(2)]
def __enter__(self):
# Assign the null pointers to stdout and stderr.
os.dup2(self.null_fds[0],1)
os.dup2(self.null_fds[1],2)
def __exit__(self, *_):
# Re-assign the real stdout/stderr back to (1) and (2)
os.dup2(self.save_fds[0],1)
os.dup2(self.save_fds[1],2)
# Close all file descriptors
for fd in self.null_fds + self.save_fds:
os.close(fd)
À utiliser il vous suffit de:
with suppress_stdout_stderr():
rogue_function()
Cela fonctionne "assez bonne". Il ne réprimer l'impression de la rogue les fonctions qui ont été encombrer mon script. J'ai remarqué en testant qu'il laisse passer ont soulevé des exceptions ainsi que certains enregistreur d'impression, et je ne suis pas tout à fait clair pourquoi. Je pense qu'il a quelque chose à voir avec quand ces messages sont envoyés sur la sortie standard stdout /stderr (je pense qu'il se passe après mon gestionnaire de contexte sorties). Si quelqu'un peut confirmer, je serais intéressé par les détails ...
- Ne cette approche (de la barre latérale) de travail?
- Au lieu de définir
sys.stdout
àStringIO()
, avez-vous essayé de le définir dans un fichier? c'est à diresys.stdout = open('log.txt','w')
- Dougal, merci, ça a l'air prometteur, je vais l'essayer demain. nullpointer, j'ai essayé de le diriger vers une coutume NullPointer() de la classe, et qui ne fonctionne pas non plus.
- merci, cela a fonctionné! Si vous êtes si incliné, post ce lien comme une réponse et je vais sélectionner.
- Je me demandais si il existe un moyen de supprimer toutes les données de sortie, et pas seulement le résultat qui vient à partir du code C. Je m'attends à ce que si je suis dans le contexte de avec suppress_stdout_stderr() ensuite, toutes les sorties doivent être intercepté. Des idées?
- Juste une remarque que j'ai édité cet extrait légèrement de sorte que tous les descripteurs de fichiers sont fermés dans
__exit__
. Sans fermer la fd dansself.save_fds
ce contexte, le gestionnaire a eu des fuites deux descripteurs de fichier à chaque fois qu'il a été appelé conduisant à l'exécution de descripteurs de fichiers dans le long processus en cours d'exécution.
Vous devez vous connecter pour publier un commentaire.
Cette approche (trouvé par le biais des barre latérale) pourrait fonctionner. Il réaffecte les descripteurs de fichier plutôt que de simplement les wrappers dans sys.stdout, etc.
De python 3.5, nous pouvons le faire avec un minimum de travail à l'aide de built-ins dans
contextlib
, à savoirredirect_stdout
etredirect_stderr
. Nous avons seulement besoin de combiner ces deux construit-dans le contexte des gestionnaires dans un contexte personnalisé gestionnaire de la nôtre, qui peut être facilement fait en utilisant le joli motif de Martijn de réponse ici. Redirection deux sorties àos.devnull
doit être sûr et portable.Noter que la suppression de
stderr
vous donnera plein retraçage quand quelque chose se brise, ce qui est une bonne chose:Quand exécuter le dessus imprime seulement les
à la borne. Les exceptions non gérées ne doit jamais passer inaperçu.
Ma solution est semblable à la vôtre, mais utilise
contextlib
et est un peu plus court et plus facile à comprendre (à mon humble avis).Le contexte pour laquelle j'ai créé ce est à ce blog. Semblable à la vôtre, je pense.
Je l'utilise comme cela dans un
setup.py
:Avez-vous essayer de rediriger stderr trop?
par exemple,
Également à l'aide de StringIO peut utiliser de la mémoire supplémentaire. Vous pouvez utiliser un mannequin de l'appareil à la place (par exemple http://coreygoldberg.blogspot.com/2009/05/python-redirect-or-turn-off-stdout-and.html).
Pas vraiment demandé par l'OP, mais j'avais besoin de cacher et de stocker la sortie, et a fait comme suit:
Utilisation:
(testé uniquement avec Python 3)
EDIT: permet maintenant de sélectionner
stderr
,stdout
ou les deux, comme dansHider([stdout, stderr])
- Je utiliser un décorateur pour cela. Il enregistre
sys.stdout
etsys.stderr
références et rend ces variables point à null. Puis, après l'exécution de la fonction de l'origine des références sont extraites. Il est important de noter le try/except bloc, qui permet la récupération des références d'origine, même si une exception est levée sur la fonction.À utiliser:
python 3.6 version de travail, testé avec des millions de suppressions sans erreurs
Si vous exécutez ce script sur un linux en fonction de la machine, vous devriez être capable de: