我有一个嘈杂的python脚本,我想通过将其stderr输出指向/ dev/null(使用bash BTW)来保持沉默.
像这样:
python -u parse.py 1> /tmp/output3.txt 2> /dev/null
但它很快就会过早退出.嗯.我无法看到追溯因为当然与stderr一起出现了.如果我不指示某个地方的stderr,它会吵闹地运行.
因此,让我们尝试将其重定向到某个地方的文件而不是/ dev/null,并查看它的输出内容:
python -u parse.py 1> /tmp/output3.txt 2> /tmp/foo || tail /tmp/foo Traceback (most recent call last): File "parse.py", line 79, inparseit('pages-articles.xml') File "parse.py", line 33, in parseit print >>sys.stderr, "bad page title", page_title UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
因此,正在生成的stderr包含utf8,并且由于某种原因,python在被重定向时拒绝打印非ascii,即使它被定向到/ dev/null(当然python当然不知道).
即使它包含utf8,我如何使python脚本的stderr静音?有没有办法在没有重写这个脚本中的每个打印到stderr?
您可以通过将stderr绑定到自定义编写器来使其静音:
#!/usr/bin/env python import codecs, sys class NullWriter: def write(self, *args, **kwargs): pass if len(sys.argv) == 2: if sys.argv[1] == '1': sys.stderr = NullWriter() elif sys.argv[1] == '2': #NOTE: sys.stderr.encoding is *read-only* # therefore the whole stderr should be replaced # encode all output using 'utf8' sys.stderr = codecs.getwriter('utf8')(sys.stderr) print >>sys.stderr, u"\u20AC" # euro sign print "ok"
例:
$ python silence_stderr.py Traceback (most recent call last): File "silence_stderr.py", line 11, inprint >>sys.stderr, u"\u20AC" UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
沉默的stderr:
$ python silence_stderr.py 1 ok
编码stderr:
$ python silence_stderr.py 2 € ok
注意:我在emacs中有上面的输出,因此可以在你可以做的终端中模拟它:
$ python ... 2>out.txt $ cat out.txt
注意:在Windows控制台内部(在chcp 65001
切换到'utf-8'并使用truetype font(Lucida Console
)之后),我得到了奇怪的结果:
C:\> python silence_stderr.py 2 Traceback (most recent call last): File "silence_stderr.py", line 14, inprint >>sys.stderr, u"\u20AC" # euro sign File "C:\pythonxy\python\lib\codecs.py", line 304, in write self.stream.write(data) IOError: [Errno 13] Permission denied
如果字体不是truetype,则异常不会引发但输出错误.
Perl适用于truetype字体:
C:\> perl -E"say qq(\x{20ac})" Wide character in print at -e line 1. €
重定向虽然有效:
C:\>python silence_stderr.py 2 2>tmp.log ok C:\>cat tmp.log € cat: write error: Permission denied
来自codecs.getwriter
文档:
查找给定编码的编解码器并返回其StreamWriter类或工厂函数.
LookupError
如果找不到编码,则引发a .
过于简化的观点:
class UTF8StreamWriter: def __init__(self, writer): self.writer = writer def write(self, s): self.writer.write(s.encode('utf-8')) sys.stderr = UTF8StreamWriter(sys.stderr)