python python-2.7

Redirigiendo stdout a "nada" en python



python-2.7 (10)

Tengo un proyecto grande que consiste en una cantidad suficientemente grande de módulos, cada uno imprimiendo algo para la salida estándar. Ahora que el proyecto ha crecido en tamaño, hay un gran no. de print declaraciones de print que imprimen mucho en el estándar que ha hecho que el programa sea considerablemente más lento.

Entonces, ahora quiero decidir en tiempo de ejecución si imprimir o no algo en el stdout. No puedo hacer cambios en los módulos ya que hay muchos. (Sé que puedo redirigir el stdout a un archivo, pero incluso esto es considerablemente lento).

Entonces mi pregunta es ¿cómo puedo redirigir el stdout a nada, es decir, cómo hago que la declaración de print no haga nada?

# 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.

Actualmente, la única idea que tengo es hacer una clase que tenga un método de escritura (que no haga nada) y redireccionar el stdout a una instancia de esta clase.

class DontPrint(object): def write(*args): pass dp = DontPrint() sys.stdout = dp

¿Hay un mecanismo incorporado en Python para esto? ¿O hay algo mejor que esto?


¿Por qué no pruebas esto?

sys.stdout.close() sys.stderr.close()


(al menos en mi sistema) parece que escribir en os.devnull es aproximadamente 5 veces más rápido que escribir en una clase DontPrint, es decir,

#!/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)

dio el siguiente resultado:

<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


En su próximo proyecto, use el módulo de registro en lugar de imprimir basura en stdout / stderr.


Multiplataforma:

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

En Windows:

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

En Linux:

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


Qué tal esto:

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()

Utiliza las funciones del módulo contextlib para ocultar el resultado de cualquier comando que intente ejecutar, según el resultado de should_hide_output() , y luego restablece el comportamiento de salida una vez que la función se ejecuta.

Si desea ocultar la salida de error estándar, importe redirect_stderr desde contextlib y agregue una línea que diga stack.enter_context(redirect_stderr(null_stream)) .

La desventaja principal es que esto solo funciona en Python 3.4 y versiones posteriores.


Si estás en Python 3.4 o superior, hay una solución simple y segura usando la biblioteca estándar:

import contextlib import os with contextlib.redirect_stdout(None): print("This won''t print!")


Si se encuentra en un entorno Unix (Linux incluido), puede redireccionar la salida a /dev/null :

python myprogram.py > /dev/null

Y para Windows:

python myprogram.py > nul


Su clase funcionará muy bien (con la excepción del nombre del método write() ; debe llamarse write() , minúscula). Solo asegúrate de guardar una copia de sys.stdout en otra variable.

Si está en un * NIX, puede hacer sys.stdout = open(''/dev/null'') , pero esto es menos portátil que rodar su propia clase.


Una buena forma de hacerlo es crear un pequeño procesador de contexto en el que envuelva sus impresiones. Luego, simplemente use está en una with -statement para silenciar todo el resultado.

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")

Al ejecutar este código solo se imprime la segunda línea de salida, no la primera:

$ python test.py this will print

Esto funciona multiplataforma (Windows + Linux + Mac OSX) y es más limpio que las otras respuestas.


sys.stdout = None

¡Está totalmente bien!

Hay una nota en los documentos :

En algunas condiciones stdin, stdout y stderr, así como los valores originales stdin , stdout y stderr pueden ser None. Suele ser el caso de las aplicaciones de Windows GUI que no están conectadas a una consola y las aplicaciones de Python que se iniciaron con pythonw.

He respondido una pregunta similar here .