This is a follow up question from here.
Where I want do go
I would like to be able to temporarily redirect the stdout into a temp file, while python still is able to print to stdout. This would involve the following steps:
- Create a copy of stdout (
new
) - Create a temp file (
tmp
) - Redirect stdout into
tmp
- Tell python to use
new
as stdout - Redirect
tmp
into the "real" stdout - Tell python to use the "real" stdout again
- Read and close
tmp
Implementation
I tried to implement the above in the following way:
import os
import subprocess
import sys
#A function that calls an external process to print to stdout as well as
#a python print to pythons stdout.
def Func(s, p = False):
subprocess.call('echo "{0}"'.format(s), shell = True)
if p:
print "print"
sil = list() # <-- Some list to store the content of the temp files
print "0.1" # Some testing of the
Func("0.2") # functionality
new = os.dup(1) # Create a copy of stdout (new)
tmp = os.tmpfile() # Create a temp file (tmp)
os.dup2(tmp.fileno(), 1) # Redirect stdout into tmp
sys.stdout = os.fdopen(new, 'w', 0) # Tell python to use new as stdout
Func("0.3", True) # <--- This should print "0.3" to the temp file and "print" to stdout
os.dup2(new, 1) # Redirect tmp into "real" stdout
sys.stdout = os.fdopen(1, 'w', 0) # Tell python to use "real" stdout again
# Read and close tmp
tmp.flush()
tmp.seek(0, os.SEEK_SET)
sil.append(tmp.read())
tmp.close()
I would like to take a little break here to summarize.
The output to console up until here should read:
0.1
0.2
print
while sil
should look like this: ['0.3\n']
. So everything is working like a charm up until here. However, if I redo the script above again like so:
print "1.1" # Some testing of the
Func("1.2") # functionality
new = os.dup(1) # Create a copy of stdout (new)
tmp = os.tmpfile() # Create a temp file (tmp)
os.dup2(tmp.fileno(), 1) # Redirect stdout into tmp
sys.stdout = os.fdopen(new, 'w', 0) # Tell python to use new as stdout
# This should print "0.3" to the temp file and "print" to stdout and is the crucial point!
Func("1.3", True)
os.dup2(new, 1) # Redirect tmp into "real" stdout
sys.stdout = os.fdopen(1, 'w', 0) # Tell python to use "real" stdout again
# Read and close tmp
tmp.flush()
tmp.seek(0, os.SEEK_SET)
sil.append(tmp.read())
an error occurs and the output looks like this:
1.1
1.2
/bin/sh: line 0: echo: write error: Bad file descriptor
print
while sil
reads: ['0.3\n', '']
.
In other words: the second Func("1.3", True)
is not able to write to the temp file.
Questions
- First of all, I would like to know why my script is not working like I want it to work. Meaning, why is it only possible in the first half of the script to write to the temp file?
- I am still a little puzzled by the usage of
dup
anddup2
. While I think I understand how the redirection of stdout into a temp file is working I totally do now know whyos.dup2(new, 1)
is doing what it is doing. Maybe the answer could elaborate on what all thedup
anddup2
s in my script are doing^^
dup
. – Tswana