Перенаправление stdout на «ничто» в python - PullRequest
113 голосов
/ 18 июля 2011

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

Итак, теперь я хочу решить в runtime , печатать ли что-либо на 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.

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

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

dp = DontPrint()
sys.stdout = dp

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

Ответы [ 10 ]

203 голосов
/ 18 июля 2011

Кроссплатформенность:

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
18 голосов
/ 23 июня 2016

Хороший способ сделать это - создать небольшой контекстный процессор, в который вы упаковываете свои отпечатки. Затем вы просто используете выражение 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.

9 голосов
/ 21 ноября 2017

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

import contextlib
import os

with contextlib.redirect_stdout(None):
  print("This won't print!")
8 голосов
/ 19 декабря 2012

(по крайней мере, в моей системе) кажется, что запись в os.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
5 голосов
/ 18 июля 2011

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

python myprogram.py > /dev/null

А для Windows:

python myprogram.py > nul
2 голосов
/ 17 марта 2016

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

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 и более поздних версиях.

1 голос
/ 20 марта 2019

Вы можете просто высмеять это.

import mock

sys.stdout = mock.MagicMock()
1 голос
/ 18 июля 2011

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

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

0 голосов
/ 06 февраля 2018
sys.stdout = None

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

В документах записка :

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

0 голосов
/ 09 марта 2017

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

sys.stdout.close()
sys.stderr.close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...