How do I print to stderr in Python?
Asked Answered
T

17

1759

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?

Transhumance answered 7/4, 2011 at 0:59 Comment(1)
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.Quick
O
1560

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
Orta answered 20/2, 2013 at 13:31 Comment(2)
In case you're writing eprint as a class method, don't forget to add self as an argument: def eprint(self, *args, **kwargs):. Otherwise you'll get your output messed up and it might take you a while to find out why :-)Vanillic
or just print('your message', file=sys.stderr) now that python2 is dead since years. See Joachim's answer below and upvote that if you like this cleaner solution.Edile
V
656
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).

Vivid answered 7/4, 2011 at 1:3 Comment(14)
@Dheeraj yes and no, pythonic to me is using the language elegantly while retaining readability. Some simple list/dict comprehensions compound statements would be more pythonic than the normal for loop, I try to opt for the more common, longer versions. I wouldn't call it pythonic.Vivid
Just don't forget to flush.Aubreyaubrie
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 readyParasite
sys.stderr.write() is nothing like print. It doesn't add a newline.Grotesque
Does't add a new line? Just put +'\n' at the end.Timmons
@Matt are you sure it applies even if stderr is redirected to file?Aubreyaubrie
This works on Python 2 and 3, which is important if you want to support both.Zelda
@SkipHuffman You mean os.linesep. This is stderr we're talking about, after all. Don't want the console to mess up with the wrong newline.Humming
This suggestion has my vote. Importing from future can break other code, and no weird syntax.Tumultuous
@Aubreyaubrie Yes. /lengthSiphonophore
To log an exception like this, use sys.stderr.write(traceback.format_exc()).Gumboil
@Matt Yes you need to flush stderr. sys.stderr.flush()Snowball
@Matt: stderr is line buffered. So it'll appear to be unbuffered if you always write stuff ending in \n to it, but it's not really the case — as can be observed in code that forgets that (unlike print()) it needs to be explicit about appending a '\n' to the string to be printed out.Departmentalism
@Matt: No-one is suggesting that Unix buffers fd 2. (Note too that that stderr man page is about the C stderr and is Linux- or glibc-specific; the C Standard just says that stderr is initially not fully buffered.) But, as you note, this question is about the behaviour of Python's sys.stderr. That has indeed changed again in Python 3.9, but sys.stderr has been line buffered to a terminal and otherwise fully buffered since at least Python 3.1.Departmentalism
K
392

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.

Kyser answered 4/4, 2013 at 10:0 Comment(2)
I suppose it's a matter of preference, but I don't see what's ugly about print('spam', file=sys.stderr). If you're doing it over and over again, you can code the 'eprint' function like in the most popular answer, but in that case, I would ask, what's wrong with logging? https://mcmap.net/q/45090/-how-do-i-print-to-stderr-in-pythonInhospitable
Another way of clarifying intent would be to do with sys.stderr as dest: before an indented call to print("ERROR", file=dest)Narcoanalysis
M
196

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.

Merous answered 23/12, 2016 at 16:4 Comment(3)
In my experience, more people use print to log messages than use logging. I think python4 should just remove print from the language and force you to use logging for that.Abjure
This is the best answer !! ... I was struggling with print or sys or who knows ... when a proper logging is needed ... thanks for the good ideaMorly
@Abjure Java does that... And now we have Kotlin.Rosenberger
W
134

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

Whitsuntide answered 8/11, 2011 at 17:29 Comment(3)
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 grammarDewhurst
@Dewhurst this all about debugging - so, I think, it's more preferable to use the simplest code as possible.Whitsuntide
This doesn't work on Python 3, so you should avoid it in new code.Zelda
C
59

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) 
Cataclysmic answered 7/4, 2011 at 1:5 Comment(10)
Opinions differ. This is the least obvious to me.Mosely
where do you have to put parantheses here?Kailyard
@AliVeli There are no parentheses, this is an older Python <=2 syntax, and therefore not Python 3 compatible.Overhaul
I would say that this is the ugliest version of all 3Pyoid
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?Ats
@EarlGray, it's just how it is. The grammar says a print statement is either print <stuff> or print >> <stuff>.Yamamoto
@EarlGray It's a holdover from C++'s stream insertion operator: std::cout << "spam";Elmiraelmo
print >> sys.stderr, 'test' no longer working (python3)Ament
What makes this beautiful? It looks like muddled mess of non-python programming languages thrown into python just to support print as a statement. That is of course one of the reasons they eliminated the print statement.Riverside
The 2020 version is as good as it gets (:Dutchman
D
39

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")
Diaconicon answered 29/12, 2013 at 21:40 Comment(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.Overhaul
D
30

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.

Deville answered 8/1, 2019 at 6:57 Comment(0)
M
23

This will mimic the standard print function but output on stderr

def print_err(*args):
    sys.stderr.write(' '.join(map(str,args)) + '\n')
Marquand answered 6/10, 2012 at 7:42 Comment(4)
I would add a sys.stderr.flush()Taipan
@Taipan - Why? print doesn't include a flush.Unreligious
Why mimic when you can actually do it?Fine
stderr is unbuffered, so flushes every time automatically. stdout flushes periodically when the buffer is full or another write is made to it later.Preponderance
O
18

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.

Overhaul answered 30/12, 2013 at 2:13 Comment(2)
Is Corey Goldberg's code best run on a Rube Goldberg machine? :PBesmear
BTW: "currying" is a (more) useful search keyword if you want to know more about "partial".Orta
H
7

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.

Hunsaker answered 1/11, 2012 at 11:58 Comment(1)
Using from __future__ import print_function is a better way to support both Python 2.6+ and Python 3.Dauntless
A
5

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.

Ave answered 10/2, 2016 at 2:29 Comment(0)
G
5

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.

Grimm answered 26/11, 2019 at 11:59 Comment(0)
B
3

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!

Bookstall answered 12/6, 2012 at 17:17 Comment(8)
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.Systaltic
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.Mccormack
I don't care about performance, for something like printing warnings.Transhumance
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")Bookstall
[1/3] Timing small snippets of code is complex, error prone, context dependent, and often leads to misleading claims like "X is consistently 1.81 times faster!"Gallonage
[2/3] Rather than writing a benchmark framework, you should use the one provided by the Standard Library's timeit module. It handles some of the common pitfalls when timing snippets of code. Some issues with the benchmark above: Python2's time.time() may not be accurate or precise depending on platform, it doesn't disable garbage collection which may run during the benchmark, it only runs 1000 iterations which doesn't produce statistically significant results. It also measures function call overhead, incrementing the iteration counter, and other code besides what it claims to measure.Gallonage
[3/3] Even if this benchmark were more accurate, it's probably not worth worrying about. As Knuth wrote: "Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."Gallonage
A corollary to @CoreyGoldberg's [3/3]: "Don't start to optimize anything until you have fully optimized the innermost loop"Julius
C
-1

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

Clodhopping answered 30/1, 2018 at 13:17 Comment(0)
B
-2

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)
Bioastronautics answered 13/1, 2022 at 22:4 Comment(0)
S
-2

Another way

import sys
print("{}".format(sys.exec_info()[1], file=sys.stderr)
Seaway answered 13/9, 2022 at 2:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.