508

Are there situations in which sys.stdout.write() is preferable to print?

(Examples: better performance; code that makes more sense)

martineau
  • 119,623
  • 25
  • 170
  • 301
Johanna Larsson
  • 10,531
  • 6
  • 39
  • 50
  • 6
    Which version of Python? 2.x or 3.x? – Mark Byers Jul 16 '10 at 09:54
  • Honestly I'd like to know for both, although I have no experience with Python 3. Updated the question. – Johanna Larsson Jul 16 '10 at 09:59
  • 27
    @S.Lott : asking for the basic differences between `sys.stdout.write()` and `print` (and/or why Python has both) is a perfectly reasonable question and does not need examples. OP did not say the command syntax was confusing. – smci Jan 20 '15 at 22:07

16 Answers16

364

print is just a thin wrapper that formats the inputs (modifiable, but by default with a space between args and newline at the end) and calls the write function of a given object. By default this object is sys.stdout, but you can pass a file using the "chevron" form. For example:

print >> open('file.txt', 'w'), 'Hello', 'World', 2+3

See: https://docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement


In Python 3.x, print becomes a function, but it is still possible to pass something other than sys.stdout thanks to the fileargument.

print('Hello', 'World', 2+3, file=open('file.txt', 'w'))

See https://docs.python.org/3/library/functions.html#print


In Python 2.6+, print is still a statement, but it can be used as a function with

from __future__ import print_function

Update: Bakuriu commented to point out that there is a small difference between the print function and the print statement (and more generally between a function and a statement).

In case of an error when evaluating arguments:

print "something", 1/0, "other" #prints only something because 1/0 raise an Exception

print("something", 1/0, "other") #doesn't print anything. The function is not called
Craig
  • 55
  • 7
luc
  • 41,928
  • 25
  • 127
  • 172
  • 85
    It's also worth noting that `print` also appends a newline to whatever you write which doesn't happen with `sys.stdout.write`. – Michael Mior Jul 16 '10 at 11:49
  • @Michael Mior: True, I've said that "it formats the inputs". Better answser would mention what kind of formatting. Thanks for clarification. – luc Jul 16 '10 at 13:35
  • 7
    Also `sys.stdout.write` is more universal if you ever need to write dual-version code (e.g. code that works simultaneously with Python 2.x as well as Python 3.x). – andreb Dec 16 '10 at 03:28
  • 3
    @MichaelMior You can suppress the newline that `print` appends with a trailing comma: `print "this",; print "on the same line as this"` – drevicko Jun 14 '14 at 15:13
  • what do you mean by the fucntion is not called? " #doesn't print anything. The func is not called" – user65165 Jul 16 '16 at 11:56
  • What's with the `>>`, or `__rshift__`, operator? – bjd2385 Feb 11 '17 at 22:47
  • 1
    @bjd2385 The `>>` is not the rshift operator here but a specific "chevron" form of the `print` statement. See https://docs.python.org/2/reference/simple_stmts.html?highlight=print#the-print-statement – luc Feb 13 '17 at 07:37
  • 9
    `sys.stdout.write()` also buffers the input and might not flush the input to the fd immediately. in order to make sure that it behaves like the print function, you should add: `sys.stdout.flush()` – kerbelp Nov 16 '17 at 07:27
  • 4
    You can use `print(blah, end="")` to prevent a newline in print. – naught101 Sep 12 '18 at 00:41
185

print first converts the object to a string (if it is not already a string). It will also put a space before the object if it is not the start of a line and a newline character at the end.

When using stdout, you need to convert the object to a string yourself (by calling "str", for example) and there is no newline character.

So

print 99

is equivalent to:

import sys
sys.stdout.write(str(99) + '\n')
Sociopath
  • 13,068
  • 19
  • 47
  • 75
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • 43
    +1 for mentioning the newline character! This is the main difference between `print` and `.write()`, I'd say. – Eric O. Lebigot Jul 16 '10 at 14:19
  • 10
    NOTE: `print` can be made to omit the newline. In Python 2.x, put a comma at the end, and a space character will be output, but no newline. E.g. `print 99,` In Python 3, `print(..., end='')` will avoid adding newline (and also avoid adding space, unless you do `end=' '`. – ToolmakerSteve Dec 19 '13 at 02:36
  • 2
    that's NOT true, `print` operation behaves slightly different in signal handlers in python2.X, i.e. print can not be replaced with sys.stdout in example: http://stackoverflow.com/questions/10777610/why-print-operation-within-signal-handler-may-change-deadlock-situation – ddzialak Oct 27 '15 at 13:13
  • for better performance let's say `print(99)` is equivalent to:```sys.stdout.write(str(99));sys.stdout.write('\n')``` – Kasra May 12 '21 at 14:41
50

Here's some sample code based on the book Learning Python by Mark Lutz that addresses your question:

import sys
temp = sys.stdout                 # store original stdout object for later
sys.stdout = open('log.txt', 'w') # redirect all prints to this log file
print("testing123")               # nothing appears at interactive prompt
print("another line")             # again nothing appears. it's written to log file instead
sys.stdout.close()                # ordinary file object
sys.stdout = temp                 # restore print commands to interactive prompt
print("back to normal")           # this shows up in the interactive prompt

Opening log.txt in a text editor will reveal the following:

testing123
another line
Peter Badida
  • 11,310
  • 10
  • 44
  • 90
Will Townes
  • 1,787
  • 1
  • 17
  • 21
  • 1
    Is there any way so that I can print to screen as well as write to the file? – Devesh Saini May 12 '14 at 04:15
  • 6
    @DeveshSaini: Yes, just overwrite sys.stdout with a proxy class that has at least a write() and flush() function. I wrote an example snippet [here](http://hastebin.com/owijihizus.py). – ponycat May 21 '14 at 09:08
43

My question is whether or not there are situations in which sys.stdout.write() is preferable to print

After finishing developing a script the other day, I uploaded it to a unix server. All my debug messages used print statements, and these do not appear on a server log.

This is a case where you may need sys.stdout.write instead.

Zearin
  • 1,474
  • 2
  • 17
  • 36
LiamSullivan
  • 611
  • 4
  • 5
  • 9
    huh? Are you sure this is a difference between `print()` and `sys.stdout.write()`, as opposed to the difference between `stdout` and `stderr`? For debugging, you should use the `logging` module, which prints messages to `stderr`. – ostrokach Jan 25 '16 at 03:05
  • 1
    Ya. Same is true with using `nohup` and redirecting to a `.out` file. – conner.xyz May 09 '16 at 15:36
  • 2
    use of sys.stdout.flush() would help. – suprit chaudhary Jun 02 '18 at 01:57
  • If you use `nohup`, by default all writing to `stdout` and `stderr` will be re-directed to `nohup.out`, disregarding whether you use `print` or `stdout.write`. – Zheng Liu Nov 15 '18 at 09:36
  • 5
    This answer is speculation and misleading/wrong, definitely should not have 40+ upvotes (as of this writing). – Gringo Suave Aug 22 '20 at 19:42
18

There's at least one situation in which you want sys.stdout instead of print.

When you want to overwrite a line without going to the next line, for instance while drawing a progress bar or a status message, you need to loop over something like

Note carriage return-> "\rMy Status Message: %s" % progress

And since print adds a newline, you are better off using sys.stdout.

Carlos
  • 5,991
  • 6
  • 43
  • 82
9

My question is whether or not there are situations in which sys.stdout.write() is preferable to print

If you're writing a command line application that can write to both files and stdout then it is handy. You can do things like:

def myfunc(outfile=None):
    if outfile is None:
        out = sys.stdout
    else:
        out = open(outfile, 'w')
    try:
        # do some stuff
        out.write(mytext + '\n')
        # ...
    finally:
        if outfile is not None:
            out.close()

It does mean you can't use the with open(outfile, 'w') as out: pattern, but sometimes it is worth it.

Hamish Downer
  • 16,603
  • 16
  • 90
  • 84
  • Strictly speaking, you _can_ use `with` -- `def process(output): # ...` / `if outfile is None: process(sys.stdout) else: with open(outfile, 'w') as out: process(out)` (adding newlines where necessary of course). It's definitely not very clean, though, that's for sure. – Nic Feb 20 '19 at 05:03
6

In Python 2.x, the print statement preprocesses what you give it, turning it into strings along the way, handling separators and newlines, and allowing redirection to a file. Python 3.x turns it into a function, but it still has the same responsibilities.

sys.stdout is a file or file-like class that has methods for writing to it which take strings or something along that line.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
5

It is preferable when dynamic printing is useful, for instance, to give information in a long process:

import time, sys
Iterations = 555
for k in range(Iterations+1):

    # Some code to execute here ...

    percentage = k / Iterations
    time_msg = "\rRunning Progress at {0:.2%} ".format(percentage)
    sys.stdout.write(time_msg)
    sys.stdout.flush()
    time.sleep(0.01)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shivid
  • 1,295
  • 1
  • 22
  • 36
  • 2
    print(time_msg, end='') instead sys.stdout.write(time_msg) sys.stdout.flush() also works – rluts Jun 12 '19 at 17:41
5

A difference between print and sys.stdout.write to point out in Python 3, is also the value which is returned when executed in the terminal. In Python 3, sys.stdout.write returns the length of the string whereas print returns just None.

So for example running following code interactively in the terminal would print out the string followed by its length, since the length is returned and output when run interactively:

>>> sys.stdout.write(" hi ")
 hi 4
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
3
>>> sys.stdout.write(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: expected a string or other character buffer object
>>> sys.stdout.write("a")
a>>> sys.stdout.write("a") ; print(1)
a1

Observing the example above:

  1. sys.stdout.write won't write non-string object, but print will

  2. sys.stdout.write won't add a new line symbol in the end, but print will

If we dive deeply,

sys.stdout is a file object which can be used for the output of print()

if file argument of print() is not specified, sys.stdout will be used

GraceMeng
  • 949
  • 8
  • 6
2

Are there situations in which sys.stdout.write() is preferable to print?

I have found that stdout works better than print in a multithreading situation. I use a queue (FIFO) to store the lines to print and I hold all threads before the print line until my print queue is empty. Even so, using print I sometimes lose the final \n on the debug I/O (using the Wing Pro IDE).

When I use std.out with \n in the string, the debug I/O formats correctly and the \n's are accurately displayed.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
  • 1
    Do you know any reason why stdout should work better than print in this case, or is this anecdotal? Could you provide a minimal working example where this happens? – user2653663 Sep 04 '18 at 08:15
  • My thinking is that stdout works at a lower level than print. I definitely had thread corruption as two print routines were fighting to feed through stdout. Writing to stdout one from each thread removed the corruption for me. – David Poundall Sep 05 '18 at 14:26
  • https://stackoverflow.com/questions/7877850/python-2-7-print-thread-safe?noredirect=1&lq=1 – Ciro Santilli OurBigBook.com Dec 16 '18 at 18:34
2

In Python 3 there is valid reason to use print over sys.stdout.write, but this reason can also be turned into a reason to use sys.stdout.write instead.

This reason is that, now print is a function in Python 3, you can override this. So you can use print everywhere in a simple script and decide those print statements need to write to stderr instead. You can now just redefine the print function, you could even change the print function global by changing it using the builtins module. Off course with file.write you can specify what file is, but with overwriting print you can also redefine the line separator, or argument separator.

The other way around is. Maybe you are absolutely certain you write to stdout, but also know you are going to change print to something else, you can decide to use sys.stdout.write, and use print for error log or something else.

So, what you use depends on how you intend to use it. print is more flexible, but that can be a reason to use and to not use it. I would still opt for flexibility instead, and choose print. Another reason to use print instead is familiarity. More people will now what you mean by print and less know sys.stdout.write.

Hielke Walinga
  • 2,677
  • 1
  • 17
  • 30
2

In Python 2, if you need to pass around a function, then you can assign os.sys.stdout.write to a variable. You cannot do this (in the REPL) with print.

>import os
>>> cmd=os.sys.stdout.write
>>> cmd('hello')
hello>>>

That works as expected.

>>> cmd=print
  File "<stdin>", line 1
    cmd=print
            ^
SyntaxError: invalid syntax

That does not work. print is a magical function.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
shanecandoit
  • 581
  • 1
  • 3
  • 11
1

Are there situations in which sys.stdout.write() is preferable to print?

For example I'm working on small function which prints stars in pyramid format upon passing the number as argument, although you can accomplish this using end="" to print in a separate line, I used sys.stdout.write in co-ordination with print to make this work. To elaborate on this stdout.write prints in the same line where as print always prints its contents in a separate line.

import sys

def printstars(count):

    if count >= 1:
        i = 1
        while (i <= count):
            x=0
            while(x<i):
                sys.stdout.write('*')
                x = x+1
            print('')
            i=i+1

printstars(5)
Sreedhar Danturthi
  • 7,119
  • 19
  • 68
  • 111
1

One of the differences is the following, when trying to print a byte into its hexadecimal appearance. For example, we know that the decimal value of 255 is 0xFF in hexadecimal appearance:

val = '{:02x}'.format(255)

sys.stdout.write(val) # Prints ff2
print(val)            # Prints ff
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
daparic
  • 3,794
  • 2
  • 36
  • 38
  • 1
    That's not what this is about. It would only happen in an interactive shell and because... `write()` did not add `\n` and returns (and interactive shell displays) function's return value (number of characters written), hexadecimal representation or any other content being displayed is immaterial. – Ondrej K. Mar 06 '20 at 18:35
1

You asked,

What is the difference between sys.stdout.write and print?`

The best way I know how to explain it is to show you how to write print in terms of sys.stdout

Below I have provided three different ways to implement python's print function:

Implementation 1

import sys

def print(*args, sep=" ", file=sys.stdout, end="\n") -> None:
    # implementation One
    file.write(sep.join(str(arg) for arg in args))
    file.write(end)

Implementation 2

def print(*args, sep=" ", file=sys.stdout, end="\n") -> None:
    # Implementation 2    
    file.write(str(args[0]))
    for arg in args[1:]:
        file.write(sep)
        file.write(str(arg))
    file.write(end)
    return

Implementation 3

def print(*args, sep=" ", file=sys.stdout, end="\n") -> None:
    # implementation 3 
    it = iter(args)
    arg = next(it)
    file.write(str(arg))
    try:
        while True:
            arg = next(it)
            file.write(sep)
            file.write(str(arg))
    except StopIteration:
        pass
    file.write(end)
    return None
Toothpick Anemone
  • 4,290
  • 2
  • 20
  • 42