Перенаправление stdout на "ничего" в python


у меня есть большой проект, состоящий из достаточно большого количества модулей, каждый из которых печатает что-то на стандартный вывод. Сейчас, когда проект вырос в размерах, больших нет. из print операторы печати много на std out, который сделал программу значительно медленнее.

Итак, теперь я хочу решить на runtime нужно ли печатать что-либо в stdout. Я не могу вносить изменения в модули, так как их много. (Я знаю, что могу перенаправление stdout в файл, но даже это значительно медленно.)

Итак, мой вопрос заключается в том, как перенаправить stdout ни на что, т. е. как мне сделать print заявление ничего не делать?

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

В настоящее время единственная идея у меня есть, чтобы сделать класс, который имеет метод записи (который ничего не делает) и перенаправить stdout на экземпляр этого класса.

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

dp = DontPrint()
sys.stdout = dp

есть ли встроенный механизм в Python для этого? Или есть что-то лучше, чем это?

9 104

9 ответов:

кросс-платформенный:

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

На Windows:

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

На Linux:

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

хороший способ сделать это-создать небольшой контекстный процессор, в который вы обернете свои отпечатки. Вы тогда просто использовать это в with-заявление, чтобы заставить замолчать все выходные.

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

при выполнении этого кода выводится только вторая строка вывода, а не первая:

$ python test.py
this will print

это работает кросс-платформенный (Windows + Linux + Mac OSX), и чище, чем те, другие ответы imho.

(по крайней мере, в моей системе) похоже, что запись в ОС.devnull примерно в 5 раз быстрее, чем запись в класс DontPrint, т. е.

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

дало следующий результат:

<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

Если вы находитесь в среде Unix (включая Linux), вы можете перенаправить вывод на /dev/null:

python myprogram.py > /dev/null

и для Windows:

python myprogram.py > nul

как насчет этого:

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

Это использует функции contextlib модуль для скрытия вывода любой команды, которую вы пытаетесь запустить, в зависимости от результата should_hide_output(), а затем восстанавливает поведение вывода после выполнения этой функции.

если вы хотите скрыть вывод стандартной ошибки, то импортируйте redirect_stderr С contextlib и добавить такую строку:stack.enter_context(redirect_stderr(null_stream)).

основной недостаток в том, что это работает только в Python 3.4 и следующие версии.

Если вы находитесь в Python 3.4 или выше, есть простое и безопасное решение с помощью стандартной библиотеки:

import contextlib
import os

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

ваш класс будет работать нормально (за исключением write() имя метода -- он должен называться write(), строчные). Просто убедитесь, что вы сохранили копию sys.stdout в другой переменной.

если вы находитесь на * NIX, вы можете сделать sys.stdout = open('/dev/null'), но это менее портативно, чем прокатывать свой собственный класс.

почему бы вам не попробовать это?

sys.stdout.close()
sys.stderr.close()
sys.stdout = None

Это нормально print() case. Но это может вызвать ошибку, если вы вызываете любой метод sys.поток stdout, например,sys.stdout.write().

есть обратите внимание, в документах:

при некоторых условиях stdin, stdout и stderr, а также оригинал значения stdin,stdout и stderr не может быть ни одного. Обычно случай для приложений с графическим интерфейсом Windows, которые не подключены к консоли и Приложения Python начались с pythonw.