Skip to content

Instantly share code, notes, and snippets.

@nilstoedtmann
Last active April 13, 2020 15:09
Show Gist options
  • Save nilstoedtmann/f1e33ae311f0ed95f6ca28d672088ecc to your computer and use it in GitHub Desktop.
Save nilstoedtmann/f1e33ae311f0ed95f6ca28d672088ecc to your computer and use it in GitHub Desktop.
Test buffering behaviour of print(), sys.stdout.write() and logging without TTY (PIPE mode)
'''Test behaviour various printing methonds without TTY.
If you run it with a TTY, all is as expected: print() and sys.stdout flush
thir buffers after each NewLine '\n':
python test-stdout-buffering.py
However, if you take the TTY away and run it in PIPE mode, then Python's
buffers much more agressively across '\n'!
true | python test-stdout-buffering.py 2>&1 | cat
Of course you can tell Python to never buffer:
true | python -u test-stdout-buffering.py 2>&1 | cat
See also:
- https://stackoverflow.com/questions/107705
'''
import logging, sys
from time import sleep
# Interestingly, gevent doesn't help! Looks like print() is not gevent'ed
#from gevent import sleep
logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger(__name__)
print('unbuffered print() before sleep', flush=True)
print('buffered print() before sleep')
sys.stdout.write('sys.stdout.write() before sleep\n')
log.info('log(): before sleep')
sleep(2)
print('unbuffered print() after sleep', flush=True)
print('buffered print() after sleep')
sys.stdout.write('sys.stdout.write() after sleep\n')
log.info('log(): after sleep')
@nilstoedtmann
Copy link
Author

This is what happens in normal TTY-mode (buffered, but buffer flashed after each NewLine \n):

$ python3 test-stdout-buffering.py

unbuffered print() before sleep
buffered print() before sleep
sys.stdout.write() before sleep
INFO:__main__:log(): before sleep

# SLEEP HERE

unbuffered print() after sleep
buffered print() after sleep
sys.stdout.write() after sleep
INFO:__main__:log(): after sleep

And this without TTY:

$ true  |  python3 test-stdout-buffering.py 2>&1  |  cat

unbuffered print() before sleep
INFO:__main__:log(): before sleep

# SLEEP HERE

buffered print() before sleep
sys.stdout.write() before sleep
unbuffered print() after sleep
INFO:__main__:log(): after sleep
buffered print() after sleep
sys.stdout.write() after sleep

@nilstoedtmann
Copy link
Author

If only I had read Disable output buffering before, in particular tzp's comment:

output buffering works differently depending on if the output goes to a tty or another process/pipe. If it goes to a tty, then it is flushed after each \n, but in a pipe it is buffered. In the latter case you can make use of these flushing solutions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment