如何在 Python 中打印到 stderr?

发布于 2024-10-30 17:40:53 字数 252 浏览 6 评论 0原文

写入 stderr 的方法有多种:

print >> sys.stderr, "spam"  # Python 2 only.

sys.stderr.write("spam\n")

os.write(2, b"spam\n")

from __future__ import print_function
print("spam", file=sys.stderr)

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

There are several ways to write to stderr:

print >> sys.stderr, "spam"  # Python 2 only.

sys.stderr.write("spam\n")

os.write(2, b"spam\n")

from __future__ import print_function
print("spam", file=sys.stderr)

What are the differences between these methods? Which method should be preferred?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(17

山人契 2024-11-06 17:40:53

我发现这是唯一一个简短、灵活、可移植且可读的函数:

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

I found this to be the only one short, flexible, portable and readable:

import sys

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

The optional function eprint saves some repetition. It can be used in the same way as the standard print function:

>>> print("Test")
Test
>>> eprint("Test")
Test
>>> eprint("foo", "bar", "baz", sep="---")
foo---bar---baz
电影里的梦 2024-11-06 17:40:53
import sys
sys.stderr.write()

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

编辑:对我来说,“Pythonic”是关于可读性和性能的第三个想法……考虑到这两件事,使用 python,80% 的代码将是 Pythonic。列表理解是不经常使用的“大事”(可读性)。

import sys
sys.stderr.write()

Is my choice, just more readable and saying exactly what you intend to do and portable across versions.

Edit: being 'pythonic' is a third thought to me over readability and performance... with these two things in mind, with python 80% of your code will be pythonic. list comprehension being the 'big thing' that isn't used as often (readability).

云柯 2024-11-06 17:40:53

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说:

旧:打印>> sys.stderr,“致命错误”
新:print("致命错误",file=sys.stderr)

对于我们许多人来说,将目标放在命令末尾感觉有些不自然。另一种选择

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

看起来更面向对象,并且优雅地从通用到特定。但请注意,write 并不是 print 的 1:1 替代品。

Python 3:

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

Python 2:

print >> sys.stderr, "fatal error"

Long answer

print >> sys.stderr is gone in Python3.
http://docs.python.org/3.0/whatsnew/3.0.html says:

Old: print >> sys.stderr, "fatal error"
New: print("fatal error", file=sys.stderr)

For many of us, it feels somewhat unnatural to relegate the destination to the end of the command. The alternative

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

looks more object oriented, and elegantly goes from the generic to the specific. But note that write is not a 1:1 replacement for print.

独夜无伴 2024-11-06 17:40:53

还没有人提到日志记录,但日志记录是专门创建的传达错误消息。基本配置将设置一个写入 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”。

Nobody's mentioned logging yet, but logging was created specifically to communicate error messages. Basic configuration will set up a stream handler writing to stderr.

This script:

# foo.py
import logging

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

has the following result when run on the command line:

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

and bar.txt will contain the 'hello world' printed on stdout.

饮湿 2024-11-06 17:40:53

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

For Python 2 my choice is:
print >> sys.stderr, 'spam'
Because you can simply print lists/dicts etc. without convert it to string.
print >> sys.stderr, {'spam': 'spam'}
instead of:
sys.stderr.write(str({'spam': 'spam'}))

夏了南城 2024-11-06 17:40:53

我想说你的第一种方法:

print >> sys.stderr, 'spam' 

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

-- 2020 年编辑 --

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

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

I would say that your first approach:

print >> sys.stderr, 'spam' 

is the "One . . . obvious way to do it" The others don't satisfy rule #1 ("Beautiful is better than ugly.")

-- Edit for 2020 --

Above was my answer for Python 2.7 in 2011. Now that Python 3 is the standard, I think the "right" answer is:

print("spam", file=sys.stderr) 
〃安静 2024-11-06 17:40:53

我使用 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")

I did the following using Python 3:

from sys import stderr

def print_err(*args, **kwargs):
    print(*args, file=stderr, **kwargs)

So now I'm able to add keyword arguments, for example, to avoid carriage return:

print_err("Error: end of the file reached. The word ", end='')
print_err(word, "was not found")
给妤﹃绝世温柔 2024-11-06 17:40:53

可以使用 print():

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

在Python 3中,几乎 框:

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

或:

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

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

In Python 3, one can just use print():

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

almost out of the box:

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

or:

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

This is straightforward and does not need to include anything besides sys.stderr.

庆幸我还是我 2024-11-06 17:40:53

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

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

This will mimic the standard print function but output on stderr

def print_err(*args):
    sys.stderr.write(' '.join(map(str,args)) + '\n')
你怎么这么可爱啊 2024-11-06 17:40:53

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

你可以通过执行以下操作来检查它是否打印到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 方法。

EDIT In hind-sight, I think the potential confusion with changing sys.stderr and not seeing the behaviour updated makes this answer not as good as just using a simple function as others have pointed out.

Using partial only saves you 1 line of code. The potential confusion is not worth saving 1 line of code.

original

To make it even easier, here's a version that uses 'partial', which is a big help in wrapping functions.

from __future__ import print_function
import sys
from functools import partial

error = partial(print, file=sys.stderr)

You then use it like so

error('An error occured!')

You can check that it's printing to stderr and not stdout by doing the following (over-riding code from 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!")

The downside to this is partial assigns the value of sys.stderr to the wrapped function at the time of creation. Which means, if you redirect stderr later it won't affect this function.
If you plan to redirect stderr, then use the **kwargs method mentioned by aaguirre on this page.

前事休说 2024-11-06 17:40:53

这同样适用于 stdout:

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

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

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

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

The same applies to stdout:

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

As stated in the other answers, print offers a pretty interface that is often more convenient (e.g. for printing debug information), while write is faster and can also be more convenient when you have to format the output exactly in certain way. I would consider maintainability as well:

  1. You may later decide to switch between stdout/stderr and a regular file.

  2. print() syntax has changed in Python 3, so if you need to support both versions, write() might be better.

失与倦" 2024-11-06 17:40:53

我正在 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 之外(它还会去哪里?),它是有效的。

I am working in python 3.4.3. I am cutting out a little typing that shows how I got here:

[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ python3
>>> import sys
>>> print("testing", file=sys.stderr)
testing
>>>
[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ 

Did it work? Try redirecting stderr to a file and see what happens:

[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]$

Well, aside from the fact that the little introduction that python gives you has been slurped into stderr (where else would it go?), it works.

可是我不能没有你 2024-11-06 17:40:53

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

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

在标头中使用:和import sys

If you want to exit a program because of a fatal error, use:

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

and import sys in the header.

仅一夜美梦 2024-11-06 17:40:53

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

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

If you do a simple test:

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))

You will find that sys.stderr.write() is consistently 1.81 times faster!

灼痛 2024-11-06 17:40:53

问题的答案是:在 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 尾随逗号在 Python3 中已成为参数,因此如果我们使用
尾随逗号以避免打印后换行,这将在
Python3 看起来像 print('Text to print', end=' ') 这是一种语法
Python2下出错。

http://python3porting.com/noconv.html

如果我们在 python3 中检查与上述情况相同的情况:

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

在 Python 2.6 下,有一个 future 导入可以将 print 变成
功能。因此,为了避免任何语法错误和其他差异,我们
应该在我们使用 print() 的任何文件中使用 from future import
打印函数。 future 导入仅适用于 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
>>>

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

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

#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

Answer to the question is : There are different way to print stderr in python but that depends on
1.) which python version we are using
2.) what exact output we want.

The differnce between print and stderr's write function:
stderr : stderr (standard error) is pipe that is built into every UNIX/Linux system, when your program crashes and prints out debugging information (like a traceback in Python), it goes to the stderr pipe.

print: print is a wrapper that formats the inputs (the input is the space between argument and the newline at the end) and it then calls the write function of a given object, the given object by default is sys.stdout, but we can pass a file i.e we can print the input in a file also.

Python2:
If we are using python2 then

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

Python2 trailing comma has in Python3 become a parameter, so if we use
trailing commas to avoid the newline after a print, this will in
Python3 look like print('Text to print', end=' ') which is a syntax
error under Python2.

http://python3porting.com/noconv.html

If we check same above sceario in python3:

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

Under Python 2.6 there is a future import to make print into a
function. So to avoid any syntax errors and other differences we
should start any file where we use print() with from future import
print_function. The future import only works under Python 2.6 and
later, so for Python 2.5 and earlier you have two options. You can
either convert the more complex print to something simpler, or you can
use a separate print function that works under both Python2 and
Python3.

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

Case: Point to be noted that sys.stderr.write() or sys.stdout.write()
( stdout (standard output) is a pipe that is built into every
UNIX/Linux system) is not a replacement for print, but yes we can use
it as a alternative in some case. Print is a wrapper which wraps the
input with space and newline at the end and uses the write function to
write. This is the reason sys.stderr.write() is faster.

Note: we can also trace and debugg using 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

小猫一只 2024-11-06 17:40:53

另一种方式

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

Another way

import sys
print("{}".format(sys.exec_info()[1], file=sys.stderr)
琴流音 2024-11-06 17:40:53

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

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

Im doing this just for fun but here is another way... :-)

message = 'error: Belly up!!'
print(message, file=sys.stderr if 'error' in message.lower() else sys.stdout)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文