web-dev-qa-db-fra.com

Redirection de stdout vers "Nothing" dans python

J'ai un grand projet constitué d'un nombre suffisamment grand de modules, chacun imprimant quelque chose sur la sortie standard. Maintenant que le projet a pris de l'ampleur, il y en a beaucoup. of print instructions imprimant beaucoup sur le std out, ce qui a considérablement ralenti le programme.

Donc, je veux maintenant décider à runtime s'il faut ou non imprimer quoi que ce soit sur la sortie standard. Je ne peux pas modifier les modules car ils sont nombreux. (Je sais que je peux rediriger la sortie standard vers un fichier, mais même cela est considérablement lent.)

Ma question est donc: comment rediriger la sortie standard vers rien, c’est-à-dire comment faire en sorte que la déclaration print ne fasse rien?

# I want to do something like this.
sys.stdout = None         # this obviously will give an error as Nonetype object does not have any write method.

Actuellement, la seule idée que j'ai est de faire une classe qui a une méthode d'écriture (qui ne fait rien) et de rediriger la sortie standard vers une instance de cette classe.

class DontPrint(object):
    def write(*args): pass

dp = DontPrint()
sys.stdout = dp

Existe-t-il un mécanisme intégré dans python pour cela? Ou y a-t-il quelque chose de mieux que cela?

114
Pushpak Dagade

Multiplate-forme:

import os
import sys
f = open(os.devnull, 'w')
sys.stdout = f

Sous Windows:

f = open('nul', 'w')
sys.stdout = f

Sous Linux:

f = open('/dev/null', 'w')
sys.stdout = f
205
Andrew Clark

Une bonne façon de faire est de créer un petit processeur de contexte dans lequel vous emballez vos impressions. Vous utilisez alors simplement une instruction with- pour faire taire toutes les sorties.

import os
import sys
from contextlib import contextmanager

@contextmanager
def silence_stdout():
    new_target = open(os.devnull, "w")
    old_target = sys.stdout
    sys.stdout = new_target
    try:
        yield new_target
    finally:
        sys.stdout = old_target

with silence_stdout():
    print("will not print")

print("this will print")

L'exécution de ce code n'imprime que la deuxième ligne de sortie, pas la première:

$ python test.py
this will print

Cela fonctionne sur plusieurs plates-formes (Windows + Linux + Mac OSX), et est plus propre que les autres réponses à mon humble avis.

18
Emil Stenström

Si vous êtes dans python 3.4 ou supérieur, il existe une solution simple et sûre qui utilise la bibliothèque standard:

import contextlib
import os

with contextlib.redirect_stdout(None):
  print("This won't print!")
9
iFreilicht

(du moins sur mon système), il apparaît que l'écriture sur os.devnull est environ 5 fois plus rapide que l'écriture sur une classe DontPrint, c'est-à-dire.

#!/usr/bin/python
import os
import sys
import datetime

ITER = 10000000
def printlots(out, it, st="abcdefghijklmnopqrstuvwxyz1234567890"):
   temp = sys.stdout
   sys.stdout = out
   i = 0
   start_t = datetime.datetime.now()
   while i < it:
      print st
      i = i+1
   end_t = datetime.datetime.now()
   sys.stdout = temp
   print out, "\n   took", end_t - start_t, "for", it, "iterations"

class devnull():
   def write(*args):
      pass


printlots(open(os.devnull, 'wb'), ITER)
printlots(devnull(), ITER)

a donné la sortie suivante:

<open file '/dev/null', mode 'wb' at 0x7f2b747044b0> 
   took 0:00:02.074853 for 10000000 iterations
<__main__.devnull instance at 0x7f2b746bae18> 
   took 0:00:09.933056 for 10000000 iterations
8
DonP

Si vous êtes dans un environnement Unix (Linux inclus), vous pouvez rediriger la sortie vers /dev/null:

python myprogram.py > /dev/null

Et pour Windows:

python myprogram.py > nul
5
Nick Radford

Que dis-tu de ça:

from contextlib import ExitStack, redirect_stdout
import os

with ExitStack() as stack:
    if should_hide_output():
        null_stream = open(os.devnull, "w")
        stack.enter_context(null_stream)
        stack.enter_context(redirect_stdout(null_stream))
    noisy_function()

Ceci utilise les fonctionnalités du module contextlib pour masquer la sortie de la commande que vous essayez d'exécuter, en fonction du résultat de should_hide_output(), puis restaure le comportement de sortie après cette fonction. est fait courir.

Si vous souhaitez masquer la sortie d'erreur standard, importez redirect_stderr De contextlib et ajoutez une ligne disant stack.enter_context(redirect_stderr(null_stream)).

Le principal inconvénient est que cela ne fonctionne que dans Python 3.4 et versions ultérieures.

2
Elias Zamaria

Votre classe fonctionnera parfaitement (à l'exception du nom de la méthode write() - elle doit s'appeler write(), en minuscule). Assurez-vous simplement de sauvegarder une copie de sys.stdout Dans une autre variable.

Si vous êtes sur un * NIX, vous pouvez faire sys.stdout = open('/dev/null'), mais c'est moins portable que de rouler votre propre classe.

1
Rafe Kettler

Vous pouvez simplement vous moquer de lui.

import mock

sys.stdout = mock.MagicMock()
1
Karthik Raja