如何在Python中打印到stderr?

时间:2011-04-07 00:59:11

标签: python printing stderr zen-of-python

有几种方法可以写入stderr:

 # Note: this first one does not work in Python 3
 print >> sys.stderr, "spam"

 sys.stderr.write("spam\n")

 os.write(2, b"spam\n")

 from __future__ import print_function
 print("spam", file=sys.stderr)

这似乎与Python#13 zen相矛盾,那么这里有什么区别,这种方式有什么优点或缺点?应该采用哪种方式?

应该有一个 - 最好只有一个 - 显而易见的方法。

17 个答案:

答案 0 :(得分:980)

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

from __future__ import print_function
import sys

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

函数eprint的使用方式与标准print函数的使用方式相同:

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

答案 1 :(得分:479)

import sys
sys.stderr.write()

是我的选择,只是更具可读性,并准确说明您打算做什么以及跨版本可移植。

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

答案 2 :(得分:130)

对于 Python 2 ,我的选择是: print >> sys.stderr, 'spam' 因为您可以简单地打印列表/ dicts等,而无需将其转换为字符串。 print >> sys.stderr, {'spam': 'spam'} 代替: sys.stderr.write(str({'spam': 'spam'}))

答案 3 :(得分:115)

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不是print的1:1替代品。

答案 4 :(得分:88)

还没有人提到logging,但是专门为了传递错误消息而创建了日志记录。默认情况下,它设置为写入stderr。这个脚本:

# foo.py
import logging
logging.basicConfig(format='%(message)s')

logging.warning('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')

(注意,logging.warndeprecated,请改用logging.warning

答案 5 :(得分:33)

我会说你的第一个方法:

print >> sys.stderr, 'spam' 

是“一个...... 显而易见的方式”其他人不满足规则#1(“美丽胜过丑陋。”)

答案 6 :(得分:30)

我使用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")

答案 7 :(得分:19)

这将模仿标准打印功能,但在stderr上输出

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

答案 8 :(得分:17)

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

使用partial只能为您节省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-and.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!")

这样做的缺点是在创建时将sys.stderr的值部分分配到包装函数。这意味着,如果您稍后重定向stderr,它将不会影响此功能。 如果您打算重定向stderr,请使用此页面上aaguirre提到的** kwargs方法。

答案 9 :(得分:7)

同样适用于stdout:

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

如其他答案所述, print 提供了一个非常方便的漂亮界面(例如用于打印调试信息),而 write 更快,也可以当你必须以某种方式确切地格式化输出时更方便。我也会考虑可维护性:

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

  2. print()语法在Python 3中已更改,因此如果您需要同时支持这两个版本, write()可能会更好。

答案 10 :(得分:7)

在Python 3中,人们只能使用print():

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

几乎开箱即用:

import sys
print("Hello, world!", file=sys.stderr)

或:

from sys import stderr
print("Hello, world!", file=stderr)

这很简单,不需要sys.stderr之外的任何内容。

答案 11 :(得分:6)

我在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]$ 

有效吗?尝试将stderr重定向到文件,看看会发生什么:

[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给你的小介绍已经悄悄进入stderr(它还会去哪里?)之外,它确实有效。

答案 12 :(得分:3)

如果你做一个简单的测试:

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 快一倍!

答案 13 :(得分:0)

尝试:

from sys import stderr


print >> sys.stderr, 'spam' 

答案 14 :(得分:0)

  

问题的答案是:在python中有不同的方法来打印stderr,但这取决于   1.)我们正在使用哪个python版本   2.)我们想要的确切输出。

print和stderr的写入功能之间的差异: stderr :stderr(标准错误)是内置于每个UNIX / Linux系统的管道,当程序崩溃并打印出调试信息(如Python中的回溯)时,它会转到stderr管道。

print :print是一个格式化输入的包装器(输入是参数和结尾处的换行符之间的空格)然后调用给定对象的write函数,给定对象默认情况下是sys.stdout,但我们可以传递一个文件,即我们也可以在文件中打印输入。

Python2: 如果我们使用python2那么

>>> import sys
>>> print "hi"
hi
>>> print("hi")
hi
>>> print >> sys.stderr.write("hi")
hi
  Python中的Python2尾随逗号已成为参数,因此如果我们使用   尾随逗号以避免打印后的换行符,这将在   Python3看起来像print('Text to print',end ='')这是一种语法   Python2下的错误。

http://python3porting.com/noconv.html

  

如果我们在python3中检查上面的相同情况:

>>> import sys
>>> print("hi")
hi
  

在Python 2.6下,有一个 future 导入来打印到   功能。所以要避免任何语法错误和其他差异我们   应该启动任何我们在将来导入时使用print()的文件   print_function。 future 导入仅适用于Python 2.6和   之后,对于Python 2.5及更早版本,您有两个选择。您可以   或者将更复杂的印刷品转换为更简单的印刷品,或者你可以   使用单独的打印功能,在Python2和Python下都可以使用   Python3。

>>> from __future__ import print_function
>>> 
>>> def printex(*args, **kwargs):
...     print(*args, file=sys.stderr, **kwargs)
... 
>>> printex("hii")
hii
>>>
  

案例:需要注意的是sys.stderr.write()或sys.stdout.write()   (stdout(标准输出)是一个内置于每个的管道   UNIX / Linux系统)不是打印的替代品,但我们可以使用   它在某些情况下是另一种选择。打印是一个包装的包装   在末尾输入空格和换行符并使用写入功能   写。这就是sys.stderr.write()更快的原因。

     

注意:我们还可以使用Logging跟踪和调试

#test.py
import logging
logging.info('This is the existing protocol.')
FORMAT = "%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logging.warning("Protocol problem: %s", "connection reset", extra=d)

https://docs.python.org/2/library/logging.html#logger-objects

答案 15 :(得分:0)

如果由于致命错误而要退出程序,请使用:

sys.exit("Your program caused a fatal error. ... description ...")

和标题中的import sys

答案 16 :(得分:-2)

import logging
logging.basicConfig(format='[%(levelname)s] %(message)s')

logging.error('is error, alarm!')
logging.warning('is simple waring')

print('hello')

pydoc logging