如何在 Python 中打印到 stderr?
- 2025-02-18 09:24:00
- admin 原创
- 40
问题描述:
有多种方法可以写入 stderr:
print >> sys.stderr, "spam" # Python 2 only.
sys.stderr.write("spam
")
os.write(2, b"spam
")
from __future__ import print_function
print("spam", file=sys.stderr)
这些方法有什么区别?应该优先选择哪种方法?
解决方案 1:
我发现这是唯一一个简短,灵活,便携且可读的:
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
解决方案 2:
import sys
sys.stderr.write()
是我的选择,更具可读性,准确说明您打算做什么,并可跨版本移植。
编辑:对于我来说,“pythonic”是可读性和性能上的第三个想法......考虑到这两点,使用 python 时 80% 的代码将是 pythonic。列表推导式是并不常用的“大事”(可读性)。
解决方案 3:
Python 3:
print("fatal error", file=sys.stderr)
Python 2:
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
")
看起来更加面向对象,并且优雅地从通用到具体。但请注意,它write
并不是 1:1 的替代品print
。
解决方案 4:
还没有人提到logging
,但日志记录是专门为传达错误消息而创建的。基本配置将设置一个写入 stderr 的流处理程序。
此脚本:
# foo.py
import 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.txt
I print to stderr by default
并且bar.txt将包含打印在标准输出上的“hello world”。
解决方案 5:
对于Python 2,我的选择是:print >> sys.stderr, 'spam'
因为您可以简单地打印列表/字典等,而无需将其转换为字符串。 print >> sys.stderr, {'spam': 'spam'}
而不是:sys.stderr.write(str({'spam': 'spam'}))
解决方案 6:
我想说你的第一种方法是:
print >> sys.stderr, 'spam'
是“一种...显而易见的方法”其他方法不满足规则 1(“美丽胜过丑陋。”)
-- 2020 年编辑 --
以上是我在 2011 年对 Python 2.7 的回答。现在 Python 3 已成为标准,我认为“正确”的答案是:
print("spam", file=sys.stderr)
解决方案 7:
我使用 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")
解决方案 8:
在 Python 3 中,只需使用print() 即可:
print(*objects, sep=' ', end='
', file=sys.stdout, flush=False)
几乎开箱即用:
import sys
print("Hello, world!", file=sys.stderr)
或者:
from sys import stderr
print("Hello, world!", file=stderr)
这很简单,除此之外不需要包含任何内容sys.stderr
。
解决方案 9:
这将模仿标准打印功能,但输出在 stderr 上
def print_err(*args):
sys.stderr.write(' '.join(map(str,args)) + '
')
解决方案 10:
编辑事后看来,我认为改变 sys.stderr 并且看不到更新的行为可能会引起混淆,这使得这个答案不如其他人指出的那样仅仅使用一个简单的函数那么好。
使用 partial 只能节省 1 行代码。潜在的混淆不值得为了节省 1 行代码而这么做。
原来的
为了使其更容易,这里有一个使用“部分”的版本,这对于包装函数有很大帮助。
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 方法。
解决方案 11:
这同样适用于 stdout:
print 'spam'
sys.stdout.write('spam
')
正如其他答案所述,print提供了一个漂亮的界面,通常更方便(例如,用于打印调试信息),而write更快,当您必须以某种方式精确格式化输出时也更方便。我也会考虑可维护性:
您稍后可能决定在 stdout/stderr 和常规文件之间切换。
print()语法在 Python 3 中发生了变化,因此如果您需要支持两个版本,write()可能会更好。
解决方案 12:
我正在使用 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(它还能去哪里?)之外,它是有效的。
解决方案 13:
如果您想因为致命错误而退出程序,请使用:
sys.exit("Your program caused a fatal error. ... description ...")
并import sys
在标题中。
解决方案 14:
如果你做一个简单的测试:
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
')
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倍!
解决方案 15:
问题的答案是:在 python 中有多种不同的方法来打印 stderr,但这取决于 1.) 我们使用的 python 版本 2.) 我们想要什么样的确切输出。
print 和 stderr 的写入函数之间的区别:
stderr:stderr(标准错误)是内置于每个 UNIX/Linux 系统的管道,当您的程序崩溃并打印出调试信息(如 Python 中的回溯)时,它会转到 stderr 管道。
print: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 中检查上述相同的场景:
>>> import sys
>>> print("hi")
hi
在 Python 2.6 下,有一个future导入可将 print 变成函数。因此,为了避免任何语法错误和其他差异,我们应该使用 from future import print_function 来启动使用 print() 的任何文件。future导入仅适用于 Python 2.6 及更高版本,因此对于 Python 2.5 及更早版本,您有两个选择。您可以将更复杂的 print 转换为更简单的内容,也可以使用在 Python2 和 Python3 下都有效的单独 print 函数。
>>> 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 系统的管道)不能替代 print,但在某些情况下我们可以将其用作替代方案。Print 是一个包装器,它在末尾用空格和换行符包装输入,并使用 write 函数进行写入。这就是 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
解决方案 16:
另一种方式
import sys
print("{}".format(sys.exec_info()[1], file=sys.stderr)
解决方案 17:
我这样做只是为了好玩,但这里还有另一种方法...... :-)
message = 'error: Belly up!!'
print(message, file=sys.stderr if 'error' in message.lower() else sys.stdout)
- 2025年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)