可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a large project consisting of sufficiently large number of modules, each printing something to the standard output. Now as the project has grown in size, there are large no. of print
statements printing a lot on the std out which has made the program considerably slower.
So, I now want to decide at runtime whether or not to print anything to the stdout. I cannot make changes in the modules as there are plenty of them. (I know I can redirect the stdout to a file but even this is considerably slow.)
So my question is how do I redirect the stdout to nothing ie how do I make the print
statement do nothing?
# 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.
Currently the only idea I have is to make a class which has a write method (which does nothing) and redirect the stdout to an instance of this class.
class DontPrint(object):
def write(*args): pass
dp = DontPrint()
sys.stdout = dp
Is there an inbuilt mechanism in python for this? Or is there something better than this?
回答1:
Cross-platform:
import os
import sys
f = open(os.devnull, 'w')
sys.stdout = f
On Windows:
f = open('nul', 'w')
sys.stdout = f
On Linux:
f = open('/dev/null', 'w')
sys.stdout = f
回答2:
A nice way to do this is to create a small context processor that you wrap your prints in. You then just use is in a with
-statement to silence all output.
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")
Running this code only prints the second line of output, not the first:
$ python test.py
this will print
This works cross-platform (Windows + Linux + Mac OSX), and is cleaner than the ones other answers imho.
回答3:
(at least on my system) it appears that writing to os.devnull is about 5x faster than writing to a DontPrint class, i.e.
#!/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)
gave the following output:
<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
回答4:
If you're in a Unix environment (Linux included), you can redirect output to /dev/null
:
python myprogram.py > /dev/null
And for Windows:
python myprogram.py > nul
回答5:
If you're in python 3.4 or higher, there's a simple and safe solution using the standard library:
import contextlib
import os
with contextlib.redirect_stdout(None):
print("This won't print!")
回答6:
How about this:
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()
This uses the features in the contextlib module to hide the output of whatever command you are trying to run, depending on the result of should_hide_output()
, and then restores the output behavior after that function is done running.
If you want to hide standard error output, then import redirect_stderr
from contextlib
and add a line saying stack.enter_context(redirect_stderr(null_stream))
.
The main downside it that this only works in Python 3.4 and later versions.
回答7:
Your class will work just fine (with the exception of the write()
method name -- it needs to be called write()
, lowercase). Just make sure you save a copy of sys.stdout
in another variable.
If you're on a *NIX, you can do sys.stdout = open('/dev/null')
, but this is less portable than rolling your own class.
回答8:
Why don't you try this?
sys.stdout.close()
sys.stderr.close()
回答9:
sys.stdout = None
It is OK for print()
case. But it can cause an error if you call any method of sys.stdout, e.g. sys.stdout.write()
.
There is a note in docs:
Under some conditions stdin, stdout and stderr as well as the original
values stdin, stdout and stderr can be None. It is usually
the case for Windows GUI apps that aren’t connected to a console and
Python apps started with pythonw.