如何在 Python 中打印到 stderr?

2025-02-18 09:24:00
admin
原创
79
摘要:问题描述:有多种方法可以写入 stderr:print >> sys.stderr, "spam" # Python 2 only. sys.stderr.write("spam ") os.write(2, b"spam ") ...

问题描述:

有多种方法可以写入 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更快,当您必须以某种方式精确格式化输出时也更方便。我也会考虑可维护性:

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

  2. 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)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2599  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1556  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。其中,技术评审与决策评审是IPD流程中至关重要的环节,它们既有明显的区别,又存在紧密的协同关系。深入理解这两者的区别与协同,对于企业有效实施IPD流程,提升产品开发效率与质量具有重要意义...
IPD管理流程   38  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、ClickUp、Freshdesk、GanttPRO、Planview、Smartsheet、Asana、Nifty、HubPlanner、Teamwork。在当今快速变化的商业环境中,项目管理软件已成为企业提升效率、优化资源分配和确保项目按时交付的关键工具。然而...
项目管理系统   32  
  建设工程项目质量关乎社会公众的生命财产安全,也影响着企业的声誉和可持续发展。高质量的建设工程不仅能为使用者提供舒适、安全的环境,还能提升城市形象,推动经济的健康发展。在实际的项目操作中,诸多因素会对工程质量产生影响,从规划设计到施工建设,再到后期的验收维护,每一个环节都至关重要。因此,探寻并运用有效的方法来提升建设工程...
工程项目管理制度   28  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用