在python中将stdout重定向到“nothing”

时间:2011-07-18 16:12:29

标签: python python-2.7

我有一个大型项目,包含足够多的模块,每个模块都打印到标准输出。现在随着项目规模的扩大,有大量的没有。 print语句在std上打印很多,这使得程序变得相当慢。

所以,我现在想在运行时决定是否向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.

目前我唯一的想法是创建一个具有write方法的类(什么都不做),并将stdout重定向到这个类的实例。

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

dp = DontPrint()
sys.stdout = dp

python中是否有内置机制?还是有比这更好的东西?

12 个答案:

答案 0 :(得分:201)

跨平台:

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

答案 1 :(得分:18)

这样做的一个好方法是创建一个小的上下文处理器来包装你的打印件。然后你只需使用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),并且比其他答案更清晰。

答案 2 :(得分:8)

(至少在我的系统上)似乎写入os.devnull比写入DontPrint类快5倍,即

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

答案 3 :(得分:7)

如果你在python 3.4或更高版本中,使用标准库是一个简单而安全的解决方案:

import contextlib
import os

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

答案 4 :(得分:5)

如果您在Unix环境(包括Linux)中,可以将输出重定向到/dev/null

python myprogram.py > /dev/null

对于Windows:

python myprogram.py > nul

答案 5 :(得分:2)

这个怎么样:

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及更高版本。

答案 6 :(得分:1)

您的类将正常工作(write()方法名称除外 - 它需要被称为write(),小写)。只需确保将sys.stdout的副本保存在另一个变量中。

如果您使用的是* NIX,则可以执行sys.stdout = open('/dev/null'),但这比滚动自己的课程便宜。

答案 7 :(得分:1)

您可以嘲笑它。

import mock

sys.stdout = mock.MagicMock()

答案 8 :(得分:0)

iFreilicht's answer的补充-适用于python 2和3。

import sys

class NonWritable:
    def write(self, *args, **kwargs):
        pass

class StdoutIgnore:
    def __enter__(self):
        self.stdout_saved = sys.stdout
        sys.stdout = NonWritable()
        return self

    def __exit__(self, *args):
        sys.stdout = self.stdout_saved

with StdoutIgnore():
    print("This won't print!")

答案 9 :(得分:0)

将在此处的众多答案中添加一些示例:

import argparse
import contextlib

class NonWritable:
    def write(self, *args, **kwargs):
        pass

parser = argparse.ArgumentParser(description='my program')
parser.add_argument("-p", "--param", help="my parameter", type=str, required=True)

#with contextlib.redirect_stdout(None): # No effect as `argparse` will output to `stderr`
#with contextlib.redirect_stderr(None): # AttributeError: 'NoneType' object has no attribute 'write'
with contextlib.redirect_stderr(NonWritable): # this works!
    args = parser.parse_args()

正常输出是:

>python TEST.py
usage: TEST.py [-h] -p PARAM
TEST.py: error: the following arguments are required: -p/--param

答案 10 :(得分:-1)

你为什么不尝试这个?

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

答案 11 :(得分:-1)

sys.stdout = None

print()案件可以。但是如果你调用sys.stdout的任何方法,它可能会导致错误,例如sys.stdout.write()

有一个note in docs

  

在某些条件下stdin,stdout和stderr以及原始版本   值 stdin stdout stderr 可以为None。通常是这样的   Windows GUI应用程序未连接到控制台的情况   Python应用程序以pythonw开头。