How to print to stderr in Python?

2019-01-02 16:16发布

I've come across several ways to write to 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)

It seems to contradict zen of Python #13 , so what's the preferred way to do it? Are there any advantages or disadvantages to one way or the other?

There should be one — and preferably only one — obvious way to do it.

15条回答
倾城一夜雪
2楼-- · 2019-01-02 16:44

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!

查看更多
萌妹纸的霸气范
3楼-- · 2019-01-02 16:48

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

from __future__ import print_function
import sys

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

The function eprint 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
查看更多
余生无你
4楼-- · 2019-01-02 16:49

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)

Unfortunately, this is quite ugly. Alternatively, use

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

but note that write is not a 1:1 replacement for print.

查看更多
唯独是你
5楼-- · 2019-01-02 16:49

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")
查看更多
深知你不懂我心
6楼-- · 2019-01-02 16:49

Try:

from sys import stderr


print >> sys.stderr, 'spam' 
查看更多
君临天下
7楼-- · 2019-01-02 16:53

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

查看更多
登录 后发表回答