在python中将stdout重定向到"nothing"

Pus*_*ade 116 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.
Run Code Online (Sandbox Code Playgroud)

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

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

dp = DontPrint()
sys.stdout = dp
Run Code Online (Sandbox Code Playgroud)

在python中有一个内置机制吗?还是有比这更好的东西?

And*_*ark 212

跨平台:

import os
import sys
f = open(os.devnull, 'w')
sys.stdout = f
Run Code Online (Sandbox Code Playgroud)

在Windows上:

f = open('nul', 'w')
sys.stdout = f
Run Code Online (Sandbox Code Playgroud)

在Linux上:

f = open('/dev/null', 'w')
sys.stdout = f
Run Code Online (Sandbox Code Playgroud)

  • 请注意,有用于取消重定向的 `sys.__stdout__`。所以你只需执行`sys.stdout = sys.__stdout__` 并且不需要存储备份。 (5认同)
  • 当然,只需保存对原始`sys.stdout`的引用并在之后重新设置它.例如,在任何其他代码之前的`old_stdout = sys.stdout`,那么当你完成时,`sys.stdout = old_stdout`. (4认同)
  • 那你怎么取消呢?有没有办法在完成后重新打开打印语句? (3认同)

Emi*_*röm 20

一个很好的方法是创建一个小的上下文处理器来包装你的打印件.然后你只需使用is-a 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")
Run Code Online (Sandbox Code Playgroud)

运行此代码只打印第二行输出,而不是第一行:

$ python test.py
this will print
Run Code Online (Sandbox Code Playgroud)

这适用于跨平台(Windows + Linux + Mac OSX),并且比其他答案更清晰.

  • ......这不是永久性的破坏者`sys.stdout`吗? (2认同)

iFr*_*cht 9

如果您使用的是python 3.4或更高版本,则可以使用标准库提供一种简单安全的解决方案:

import contextlib

with contextlib.redirect_stdout(None):
  print("This won't print!")
Run Code Online (Sandbox Code Playgroud)

  • 使用contextlib.redirect_stdout(None)也可以 (3认同)

小智 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)
Run Code Online (Sandbox Code Playgroud)

给出了以下输出:

<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
Run Code Online (Sandbox Code Playgroud)

  • 只是为了记录,下次你想要时间,只需使用[timeit](https://docs.python.org/2/library/timeit.html) (4认同)
  • 当然/ dev/null很快......它是"网络规模"! (4认同)

Nic*_*ord 5

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

python myprogram.py > /dev/null
Run Code Online (Sandbox Code Playgroud)

对于Windows:

python myprogram.py > nul
Run Code Online (Sandbox Code Playgroud)

  • 最好有一个适用于所有平台的解决方案. (2认同)
  • 也许是@Guanidene,但如果他是唯一使用他的程序的人,他几乎可以保证环境. (2认同)