I've come across at least three ways to print to stderr:

 import sys

 print >> sys.stderr, 'spam'

 sys.stderr.write('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.

share|improve this question
30  
The first way listed is one of the many things removed in Python 3. The consensus seems to be that the >> syntax was ugly anyway, and since print is now a function, the syntax would never work. – Steve Howard Aug 5 '11 at 21:50
14  
Here's another one to add to your list: os.write(2, "spam\n") – Will Hardy Jul 10 '13 at 10:54
5  
I use: sys.exit('Error: <error text>') – stark Jul 31 '13 at 14:05
24  
It's too bad none of the 3 ways are obvious. – RustyX Sep 21 '14 at 18:47

12 Answers 12

up vote 602 down vote accepted

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 was as the standard print function:

>>> print("Test")
Test
>>> eprint("Test")
Test
>>> eprint("foo", "bar", "baz", sep="---")
foo---bar---baz
share|improve this answer
51  
This is by far the best option, since it gets you set up nicely for Python 3, even if you are using Python 2 or Jython at the moment. – Mark Booth Jun 17 '13 at 21:49
17  
Agreed. This is all I use. It's future-proof, more consistent (pythonic) to use print as a function, and clearer (i.e., what the hell is ">>"? This isn't C++!! ;-)). – JJC Jun 27 '13 at 12:36
14  
Just one thought: since this will import the print function, every other "print" in the original script will now need to be "functionized" adding "(" and ")". So that is a slight strike against this method, IMO. – Dan H Nov 12 '14 at 18:38
10  
@DanH Yes this forces you to make your code Python3-ready. I guess this could be why many people actually like it! – MarcH Nov 18 '14 at 19:00
11  
@MarkH... yes, it forces you to make your code Python3-ready... it also forces you to do it NOW, just to print some debugging info to the stderr... which I would find more of a hassle in most situations when I'm trying to debug something. (I'd rather not introduce new syntax errors!) :-) – Dan H Nov 20 '14 at 14:49

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

share|improve this answer
19  
Isn't readability the same as being pythonic? – Dheeraj V.S. Nov 26 '11 at 17:49
44  
Just don't forget to flush. – temoto Apr 3 '12 at 19:00
9  
Advantage of the print statement is easy printing of non-string values, without having to convert them first. If you need a print statement, I would therefore recommend using the 3rd option to be python 3 ready – vdboor Apr 6 '12 at 11:22
38  
sys.stderr.write() is nothing like print. It doesn't add a newline. – Colonel Panic May 18 '12 at 14:27
17  
@temoto - stderr isn't buffered, so no need to flush. – Matt Jan 13 '13 at 3:18

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

share|improve this answer
5  
The more Pythonic way to print a dictionary would be with something like "{0}".format({'spam': 'spam'}) anyway, wouldn't it? I would say you should avoid explicitly converting to string. Edit: I accidentally a grammar – luketparkinson Jun 23 '12 at 11:54
1  
@luketparkinson this all about debugging - so, I think, it's more preferable to use the simplest code as possible. – Frankovskyi Bogdan Mar 24 '13 at 23:33
70  
This doesn't work on Python 3, so you should avoid it in new code. – JonnyJD Apr 23 '13 at 10:04

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.

share|improve this answer

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

share|improve this answer
87  
Opinions differ. This is the least obvious to me. – porgarmingduod Apr 7 '11 at 6:39
1  
@AliVeli There are no parentheses, this is an older Python <=2 syntax, and therefore not Python 3 compatible. – Rebs Dec 30 '13 at 2:07
14  
I would say that this is the ugliest version of all 3 – volcano Jan 20 '14 at 22:25
3  
What does that >> mean syntactically? I understand that it's an effort to copy bash's >, so is it some shoehorned syntax to do just that? – Dmytro Sirenko Feb 7 '14 at 22:06
1  
@EarlGray, it's just how it is. The grammar says a print statement is either print <stuff> or print >> <stuff>. – leewz Dec 10 '15 at 2:02

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")
share|improve this answer
1  
I was going to suggest that you could use a partial too, but realised that partial assigns the stderr to the function at the creation time of the partial. This prevents you redirecting stderr later as the partial will still hold the original stderr object. – Rebs Dec 30 '13 at 2:26

This will mimic the standard print function but output on stderr

def print_err(*args):
    sys.stderr.write(' '.join(map(str,args)) + '\n')
share|improve this answer
5  
I would add a sys.stderr.flush() – AMS May 6 '14 at 11:59
3  
@AMS - Why? print doesn't include a flush. – Robᵩ Oct 1 '14 at 19:51
2  
Why mimic when you can actually do it? – Mad Physicist Nov 5 '15 at 14:15

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.

share|improve this answer
    
Is Corey Goldberg's code best run on a Rube Goldberg machine? :P – Agi Hammerthief Nov 10 '15 at 21:53
1  
BTW: "currying" is a (more) useful search keyword if you want to know more about "partial". – MarcH Dec 31 '15 at 22:58

Nobody's mentioned logging yet, but logging was created specifically to communicate error messages. By default it is set up to write to stderr. This script:

# foo.py
import logging
logging.basicConfig(format='%(message)s')

logging.warn('I print to stderr by default')
logging.info('For this you must change the level and add a handler.')
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 contains the 'hello world')

share|improve this answer

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.

share|improve this answer
1  
Using from __future__ import print_function is a better way to support both Python 2.6+ and Python 3. – phoenix Mar 2 '16 at 23:57

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.

share|improve this answer

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!

share|improve this answer
    
If I run this I see a much smaller difference. It's interesting that most answers ignore the print function (python 3) way. I've never used it before (inertia), but thought I'd run this timing script and add the print function. Direct comparison of print statement and function isn't possible (import from future applies to the whole file and masks the print statement) but rewriting this code to use the print function instead of statement I see a bigger speed up (~1.6 though somewhat variable) in favour of the print function. – hamish Nov 8 '12 at 10:03
1  
The result of this test is somehow misleading. Print 'XXXXXXXXXXXXXXXXXXXX' instead of 'X' and the ratio drops to 1.05. I assume most python programs need to print more than a single character. – Always Asking Jun 26 '13 at 13:45
10  
I don't care about performance, for something like printing warnings. – wim Dec 31 '13 at 15:22
    
I know it's been a while, but you replied equally long after my post... If you don't car about performance than I would suggest the more pythonic way would be to use sys.stderr.write and not the WTF?!? ">>" characters. If this sys.stdout namespace is too long you could rename it... (ie. from sys import stderr as stderr_fh). Then you can do stderr_fh.write("blah") – ThePracticalOne Jul 2 '14 at 22:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.