Skip to content Skip to sidebar Skip to footer

Intercepting Assignments To Sys.stdout And Sys.stderr

The sys module has a couple of global properties that I'm interested in: sys.stdout and sys.stderr. I'm building a module of my own, that (among other things), replaces sys.stdout

Solution 1:

The only real way to completely override stdout on python is to actually override the stdout file descriptor (1). This can be done using the dup2 syscall.

Below is a cross-platform example showing how to override stdout, allowing to use custom logic on all data written to it. In this example, the logic just duplicates all characters written to stdout.

import os
import sys
import threading

defhandle_stdout(fake_stdout, real_stdout):
    whilenot fake_stdout.closed andnot real_stdout.closed:
        char = fake_stdout.read(1)
        real_stdout.write(char * 2)

defoverride_stdout():
    stdout_fd = 1
    pipe_reader_fd, pipe_writer_fd = os.pipe()
    pipe_reader = os.fdopen(pipe_reader_fd, 'r')
    original_stdout_writer = os.fdopen(os.dup(stdout_fd), 'w')
    os.dup2(pipe_writer_fd, stdout_fd)
    return pipe_reader, original_stdout_writer

# Override stdout
pipe_reader, original_stdout_writer = override_stdout()
thread = threading.Thread(target=handle_stdout, args=(pipe_reader, original_stdout_writer))
thread.start()

# Write stuff to stdoutprint('foobar')

# Cleanup to allow background thread to shut down
pipe_reader.close()
original_stdout_writer.close()

Running this example will output:

ffoooobbaarr

For some versions of python, you'll have to set the PYTHONLEGACYWINDOWSSTDIO environment variable to a non-empty string to make this example to work on windows.

Post a Comment for "Intercepting Assignments To Sys.stdout And Sys.stderr"