如何在Python中打印到stderr?

如何在Python中打印到stderr?有几种写stderr的方法:#Note:thisfirstonedoesnotworkinPython3print>>sys.stderr,”spam”

有几种写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)

这似乎与zen的Python#13 相矛盾,所以这里有什么区别,一种方式或另一种方式有什么优点或缺点? 应该使用哪种方式?

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


#1楼

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

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


#2楼

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

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

#3楼

同样适用于标准输出:

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

如在其他答案中所述, 打印提供了一个漂亮的界面,该界面通常更方便(例如,用于打印调试信息),而写入速度更快,并且当您必须以某种特定方式精确格式化输出时也可以更加方便。 我也会考虑可维护性:

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

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


#4楼

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

from __future__ import print_function
import sys

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

可以使用与标准print功能相同的方式使用eprint功能:

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

#5楼

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不能以1:1替代print


#6楼

我使用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楼

编辑在事后看来,我认为与更改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!')

您可以执行以下操作(来自http://coreygoldberg.blogspot.com.au/2009/05/python-redirect-or-turn-off-stdout-和.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方法。


#8楼

我正在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中(它还能去哪里?),它还能工作。


#9楼

还没有人提到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.warn已被弃用 ,请改用logging.warning


#10楼

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

print和stderr的write函数之间的区别: 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

Python2中的Python2尾部逗号已成为参数,因此,如果我们使用尾部逗号来避免打印后出现换行符,则在Python3中,这将类似于print(’Text to print’,end =”),这是Python2下的语法错误。

http://python3porting.com/noconv.html

如果我们在python3中的sceario上面检查相同的内容

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

在Python 2.6下,有一个将来的导入可以使打印成为函数。 因此,为避免任何语法错误和其他差异,我们应从将来的 import print_function开始使用print()的任何文件。 将来的导入仅在Python 2.6和更高版本下有效,因此对于Python 2.5和更低版本,您有两个选择。 您可以将更复杂的打印转换为更简单的打印,也可以使用在Python2和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系统中内置的管道)不能代替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


#11楼

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

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

print('hello')

pydoc日志记录


#12楼

在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之外的任何内容。


#13楼

import sys
sys.stderr.write()

是我的选择,更具可读性,并说出您打算做什么,并且可以跨版本移植。

编辑:“ pythonic”是我对可读性和性能的第三种思考……考虑到这两点,使用python 80%的代码将是pythonic。 列表理解是不经常使用的“大事”(可读性)。


#14楼

我会说你的第一种方法:

print >> sys.stderr, 'spam' 

是“……一种显而易见的方式”,而另一种则不满足规则1(“美丽胜于丑陋”。)


#15楼

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

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

并在标题中import sys


#16楼

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

今天的文章如何在Python中打印到stderr?分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/8861.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注