How to Check if Python’s Output Buffering Is Enabled

Buffering

Update (2020-10-12): Since Python 3.9, sys.stderr is line-buffered, which helps mitigate some of the problems with output not appearing.

By default, Python buffers output to standard output (stdout) and standard error (stderr). This means that output from your code might not show up immediately, making debugging harder.

To disable output buffering, you can run Python with the -u option or by setting the PYTHONUNBUFFERED environment variable. However, there’s no documented way of checking if output buffering is enabled from within Python.

It’s possible to detect it by checking sys.stdout, which is an io.TextIOWrapper object. This takes one argument, a buffered text stream to wrap, which you can access at sys.stdout.buffer.

When output buffering is enabled, sys.stdout.buffer will be an io.BufferedWriter object:

$ python -c 'import sys; print(sys.stdout.buffer)'
<_io.BufferedWriter name='<stdout>'>

When output buffering is disabled, sys.stdout.buffer will the underlying io.FileIO object:

$ python -u -c 'import sys; print(sys.stdout.buffer)'
<_io.FileIO name='<stdout>' mode='wb' closefd=False>

Some programs wrap sys.stdout with extra layers, for example pytest does so to capture output. To guard against these situations, you should instead check sys.__stdout__ object, which holds the original value for sys.stdout when Python started. So an accurate check for output buffering would check if sys.__stdout__ uses a BufferedWriter:

import io
import sys


def output_buffering_enabled():
    return isinstance(sys.__stdout__.buffer, io.BufferedWriter)

Fin

May your buffering problems be over,

—Adam


Learn how to make your tests run quickly in my book Speed Up Your Django Tests.


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: