如何在Python中打印到stderr?

有几种方法可以写入stderr:

print >> sys.stderr, "spam"  # Python 2 only.
sys.stderr.write("spam\n")
os.write(2, b"spam\n")
from __future__ import print_functionprint("spam", file=sys.stderr)

这些方法有什么区别?应该首选哪种方法?

1158866 次浏览
import syssys.stderr.write()

是我的选择,只是更具可读性,确切地说你打算做什么,并跨版本移植。

编辑:成为“pythonic”是我对易读性和性能的第三个想法……考虑到这两件事,使用python 80%的代码将是pythonic。

我想说你的第一个方法:

print >> sys.stderr, 'spam'

是“一个 . . . 明显的方法来做到这一点”其他人不满足规则#1(“美丽比丑陋更好。

--编辑2020--

以上是我在2011年对Python 2.7的回答。现在Python 3是标准,我认为“正确”的答案是:

print("spam", file=sys.stderr)

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

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

import timeimport sys
def run1(runs):x = 0cur = time.time()while x < runs:x += 1print >> sys.stderr, 'X'elapsed = (time.time()-cur)return elapsed
def run2(runs):x = 0cur = time.time()while x < runs:x += 1sys.stderr.write('X\n')sys.stderr.flush()elapsed = (time.time()-cur)return elapsed
def compare(runs):sum1, sum2 = 0, 0x = 0while x < runs:x += 1sum1 += 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倍!

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

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

这同样适用于stdout:

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

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

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

  2. print()语法在Python 3中发生了变化,所以如果你需要支持两个版本,可不可以写()

我发现这是唯一一个简短,灵活,便携和可读性:

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

python3:

print("fatal error", file=sys.stderr)

python2:

print >> sys.stderr, "fatal error"

冗长的回答

print >> sys.stderr在Python3中消失了。http://docs.python.org/3.0/whatsnew/3.0.html表示:

原版本:print >> sys.stderr, "fatal error"
新增:print("fatal error", file=sys.stderr)

对我们中的许多人来说,把目的地放在命令的末尾有点不自然

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

看起来更面向对象,优雅地从通用到特定。但请注意,write不是print的1: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")

编辑事后看来,我认为改变sys.stderr和没有看到行为更新的潜在混淆使得这个答案不如其他人指出的仅仅使用一个简单的函数。

使用部分仅为您节省1行代码。潜在的混乱不值得节省1行代码。

原始

为了使其更容易,这里有一个使用“部分”的版本,这对包装函数有很大帮助。

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

然后你就像这样使用它

error('An error occured!')

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

# over-ride stderr to prove that this function works.class NullDevice():def write(self, s):passsys.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.pyfrom print_error import error
# no message should be printederror("You won't see this error!")

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

我正在使用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.txtPython 3.4.3 (default, May  5 2015, 17:58:45)[GCC 4.9.2] on cygwinType "help", "copyright", "credits" or "license" for more information.testing
[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$

好吧,除了python给你的小介绍已经被塞进stderr之外(它还会去哪里?),它是有效的。

还没有人提到#0,但日志记录是专门为传达错误消息而创建的。基本配置将设置一个写入stderr的流处理程序。

这个脚本:

# foo.pyimport logging
logging.basicConfig(format='%(message)s')log = logging.getLogger(__name__)log.warning('I print to stderr by default')print('hello world')

在命令行上运行时会产生以下结果:

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

bar.txt将包含打印在stdout上的“hello world”。

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

print和stderr的写函数之间的区别:stderr(标准错误)是每个UNIX/Linux系统中内置的管道,当您的程序崩溃并打印出调试信息(如Python中的回溯)时,它会进入stderr管道。

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

Python2:如果我们使用python2,那么

>>> import sys>>> print "hi"hi>>> print("hi")hi>>> print >> sys.stderr.write("hi")hi

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

http://python3porting.com/noconv.html

如果我们在python3中检查上面的sceario:

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

在Python 2.6下,有一个未来导入来将打印转换为因此,为了避免任何语法错误和其他差异,我们应该从未来导入开始使用print()的任何文件print_function未来导入仅适用于Python 2.6和之后,因此对于Python 2.5及更早版本,您有两个选项。您可以要么将更复杂的打印转换为更简单的打印,要么您可以使用在Python2和Python2下工作的单独打印函数Python3。

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

case:sys.stderr.write()或sys.stdout.write()(stdout(标准输出)是一个内置于每个UNIX/Linux系统)不是打印的替代品,但我们可以使用在某些情况下,它作为一种替代方案。打印是包装在末尾使用空格和换行符输入,并使用写函数来这就是sys.stderr.write()更快的原因。

备注:我们还可以使用日志记录跟踪和调试

#test.pyimport logginglogging.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

在Python 3中,可以使用print():

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

几乎从盒子里出来:

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

或:

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

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

如果您想因为致命错误而退出程序,请使用:

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

import sys在标题中。

我这样做只是为了好玩,但这是另一种方式…:-)

message = 'error: Belly up!!'print(message, file=sys.stderr if 'error' in message.lower() else sys.stdout)

另一种方式

import sysprint("{}".format(sys.exec_info()[1], file=sys.stderr)