如何在 Python 中打印到 stderr?

2025-02-18 09:24:00
admin
原创
38
摘要:问题描述:有多种方法可以写入 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)
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1325  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它涵盖了从产品概念产生到产品退市的整个生命周期,通过整合跨部门团队、优化流程等方式,显著提升产品开发的效率和质量,进而为项目的成功奠定坚实基础。深入探究IPD流程的五个阶段与项目成功之间...
IPD流程分为几个阶段   4  
  华为作为全球知名的科技企业,其成功背后的管理体系备受关注。IPD(集成产品开发)流程作为华为核心的产品开发管理模式,其中的创新管理与实践更是蕴含着丰富的经验和深刻的智慧,对众多企业具有重要的借鉴意义。IPD流程的核心架构IPD流程旨在打破部门墙,实现跨部门的高效协作,将产品开发视为一个整体的流程。它涵盖了从市场需求分析...
华为IPD是什么   3  
  IPD(Integrated Product Development)研发管理体系作为一种先进的产品开发模式,在众多企业的发展历程中发挥了至关重要的作用。它不仅仅是一套流程,更是一种理念,一种能够全方位提升企业竞争力,推动企业持续发展的有效工具。深入探究IPD研发管理体系如何助力企业持续发展,对于众多渴望在市场中立足并...
IPD管理流程   3  
  IPD(Integrated Product Development)流程管理旨在通过整合产品开发流程、团队和资源,实现产品的快速、高质量交付。在这一过程中,有效降低成本是企业提升竞争力的关键。通过优化IPD流程管理中的各个环节,可以在不牺牲产品质量和性能的前提下,实现成本的显著降低,为企业创造更大的价值。优化产品规划...
IPD流程分为几个阶段   4  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用