This is a follow up question from here specifically concerning its answer.
From a python module I am calling a Hello World executable that simply prints Hello World
to the stdout. I am interested in redirecting that output to a python StringIO
and ran into this answer which almost brings me all the way to the solution.
The critical part of this answer is this code segment:
1. def redirect_stdout():
2. print "Redirecting stdout"
3. sys.stdout.flush() # <--- important when redirecting to files
4. newstdout = os.dup(1)
5. devnull = os.open('/dev/null', os.O_WRONLY)
6. os.dup2(devnull, 1)
7. os.close(devnull)
8. sys.stdout = os.fdopen(newstdout, 'w')
Also I would like to restore the stdout as it was before the redirection.
dup
and dup2
doing?/dev/null
?sys.stdout = os.fdopen(newstdout, 'w')
)StringIO
object?I am pretty sure that once I have the answer for my question 1 that the answers of questions 2 and 3 will be easy. I decided to post them anyway to maybe push the answer of question 1 into the direction where I want to go.
stdout = original print('This string goes to stdout, NOT the file! ') if __name__ == '__main__':Redirecting stdout / stderr redirect_to_file('Python rocks! ') Here we just import Python's sys module and create a function that we can pass strings that we want to have redirected to a file.
As redirection is a method of capturing a program output and sending it as an input to another command or file. The I/O streams can be redirected by putting the n> operator in use, where n is the file descriptor number. For redirecting stdout, we use “1>” and for stderr, “2>” is added as an operator.
A built-in file object that is analogous to the interpreter's standard output stream in Python. stdout is used to display output directly to the screen console. Output can be of any form, it can be output from a print statement, an expression statement, and even a prompt direct for input.
I've written below a few additional comments that should make clearer what it's going on inside the redirect_stdout
function:
def redirect_stdout():
print "Redirecting stdout"
sys.stdout.flush() # <--- important when redirecting to files
# Duplicate stdout (file descriptor 1)
# to a different file descriptor number
newstdout = os.dup(1)
# /dev/null is used just to discard what is being printed
devnull = os.open('/dev/null', os.O_WRONLY)
# Duplicate the file descriptor for /dev/null
# and overwrite the value for stdout (file descriptor 1)
os.dup2(devnull, 1)
# Close devnull after duplication (no longer needed)
os.close(devnull)
# Use the original stdout to still be able
# to print to stdout within python
sys.stdout = os.fdopen(newstdout, 'w')
One important thing to note is that a process gets three different file descriptors from the OS when launched:
As explained in the comments, the code above takes advantage of the file descriptor for stdout and the file descriptor duplication functions to make trick the C code into using a different stdout while still keeping a reference to the original stdout in the python code to be able to print.
/dev/null
is a special device file (everything in UNIX is a file!) that swallows everything written to it like a black hole. dup
duplicates a file descriptor. If you are used to Windows, a file descriptor in UNIX is a special integer which represents an open file, it's like a Windows file handle.
The program is opening /dev/null
for writing (only), taking a copy of it's file descriptor, closing the open file (because having a file descriptor is enough for UNIX to write to a file, you don't need to keep the resources open), then assigning the open file to sys.stdout
.
Remember sys
is the Python module which represents all sorts of system-specific resources, such as the file system. So, in UNIX sys.stdout
will represent /dev/stdout
i.e. the system STDOUT
stream.
So, altogether, this code is fooling Python into thinking that /dev/null/
is STDOUT
so now every time your program writes to STDOUT
with, say, the print
statement (function in Python3) then it will really be writing to /dev/null
and you will never see the resulting text on your console.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With