如何打印到Python的标准错误?

我遇到至less三种打印到stderr的方法:

import sys print >> sys.stderr, 'spam' sys.stderr.write('spam\n') from __future__ import print_function print('spam', file=sys.stderr) 

这似乎与Python#13 †的 禅宗相矛盾,所以最好的方法是什么? 这种或那种方式有什么优点或缺点?

应该有一个 – 而且最好只有一个 – 明显的方法来做到这一点。

我发现这是唯一一个短+灵活+便携+可读的:

 from __future__ import print_function import sys def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) 

functioneprint可以和标准printfunction一样使用:

 >>> print("Test") Test >>> eprint("Test") Test >>> eprint("foo", "bar", "baz", sep="---") foo---bar---baz 

sys.stderr.write()是我的select,只是更具可读性,并准确地说明你打算做什么和跨版本的移植。

编辑:“pythonic”是我在可读性和性能方面的第三个想法…考虑到这两件事情,python 80%的代码将pythonic。 列表理解是不常用的“大事”(可读性)。

对于Python 2,我的select是: print >> sys.stderr, 'spam'因为您可以简单地打印列表/字典等,而不必将其转换为string。 print >> sys.stderr, {'spam': 'spam'}而不是: sys.stderr.write(str({'spam': 'spam'}))

print >> sys.stderr在Python3中没有了。 http://docs.python.org/3.0/whatsnew/3.0.html说:;

 Old: print >>sys.stderr, "fatal error" New: print("fatal error", file=sys.stderr) 

不幸的是,这是相当丑陋的。 或者,使用

 sys.stderr.write("fatal error\n") 

但请注意, write不是1:1的printreplace。

我会说你的第一个方法:

 print >> sys.stderr, 'spam' 

是“一个明显的做法”,其他人不满足规则1(“美丽胜于丑陋”)。

我使用Python 3做了以下工作:

 from sys import stderr def print_err(*args, **kwargs): print(*args, file=stderr, **kwargs) 

所以现在我可以添加关键字参数,例如,以避免回车:

 print_err("Error: end of the file reached. The word ", end='') print_err(word, "was not found") 

这将模仿标准的打印function,但在stderr上输出

 def print_err(*args): sys.stderr.write(' '.join(map(str,args)) + '\n') 

没有人提到logging ,但日志logging是专门为了传达错误消息而创build的。 默认情况下,它被设置为写入标准错误。 这个脚本:

 # foo.py import logging logging.basicConfig(format='%(message)s') logging.warn('I print to stderr by default') logging.info('For this you must change the level and add a handler.') print('hello world') 

在命令行上运行时有以下结果:

 $ python3 foo.py > bar.txt I print to stderr by default 

(而bar.txt包含'hello world')

编辑在后视中,我认为与sys.stderr不断更新的潜在混淆,并没有看到更新的行为,使得这个答案不如其他人指出的那样使用简单的函数。

使用部分只能保存1行代码。 潜在的混淆不值得保存1行代码。

原版的

为了使它更容易,这里是一个使用“partial”的版本,这在包装函数中是一个很大的帮助。

 from __future__ import print_function import sys from functools import partial error = partial(print, file=sys.stderr) 

你然后像这样使用它

 error('An error occured!') 

您可以通过执行以下操作来检查是否打印到stderr而不是stdout(来自http://coreygoldberg.blogspot.com.au/2009/05/python-redirect-or-turn-off-stdout-的优先代码;.html ):

 # over-ride stderr to prove that this function works. class NullDevice(): def write(self, s): pass sys.stderr = NullDevice() # we must import print error AFTER we've removed the null device because # it has been assigned and will not be re-evaluated. # assume error function is in print_error.py from print_error import error # no message should be printed error("You won't see this error!") 

这个缺点是在创build时将sys.stderr的值赋给了被包装的函数。 这意味着, 如果稍后redirectstderr,则不会影响此function。 如果您打算redirectstderr,请使用此页面上的aaguirre提及的** kwargs方法。

这同样适用于stdout:

 print 'spam' sys.stdout.write('spam\n') 

正如在其他答案中所述, 打印提供了一个非常漂亮的界面,通常更方便(例如打印debugging信息),而写入速度更快,而且当您必须以某种方式精确地格式化输出时,打印也会更方便。 我也会考虑可维护性:

  1. 您稍后可能决定在stdout / stderr和常规文件之间切换。

  2. print()语法在Python 3中已经改变了,所以如果你需要支持这两个版本, write()可能会更好。

我正在python 3.4.3工作。 我正在削减一些打字,显示我是如何到达这里的:

 [18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ python3 >>> import sys >>> print("testing", file=sys.stderr) testing >>> [18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ 

有用吗? 尝试将stderrredirect到一个文件,看看会发生什么:

 [18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ python3 2> /tmp/test.txt >>> import sys >>> print("testing", file=sys.stderr) >>> [18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ [18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ cat /tmp/test.txt Python 3.4.3 (default, May 5 2015, 17:58:45) [GCC 4.9.2] on cygwin Type "help", "copyright", "credits" or "license" for more information. testing [18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ 

那么,除了python给你的小小的介绍已经嗤之以鼻的地方(还有什么地方会去?)之外,它是有效的。

如果你做一个简单的testing:

 import time import sys def run1(runs): x = 0 cur = time.time() while x < runs: x += 1 print >> sys.stderr, 'X' elapsed = (time.time()-cur) return elapsed def run2(runs): x = 0 cur = time.time() while x < runs: x += 1 sys.stderr.write('X\n') sys.stderr.flush() elapsed = (time.time()-cur) return elapsed def compare(runs): sum1, sum2 = 0, 0 x = 0 while x < runs: x += 1 sum1 += run1(runs) sum2 += run2(runs) return sum1, sum2 if __name__ == '__main__': s1, s2 = compare(1000) print "Using (print >> sys.stderr, 'X'): %s" %(s1) print "Using (sys.stderr.write('X'),sys.stderr.flush()):%s" %(s2) print "Ratio: %f" %(float(s1) / float(s2)) 

你会发现sys.stderr.write()的速度是1.81倍!