Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write to stdout after redirecting FD

Tags:

python

stdout

Please take a look at this python code below.

so = open('/tmp/test.log', 'a+')
os.dup2(so.fileno(), sys.stdout.fileno())

After executing that piece of code I would like to still have possibility to print something on standard stdout.


I already tried:

print('Foo\n', file=sys.__stdout__)

As according to documentation could be a way to go.

sys.__stdin__
sys.__stdout__
sys.__stderr__

These objects contain the original values of stdin, stderr and stdout at the start of the program. They are used during finalization, and could be useful to print to the actual standard stream no matter if the sys.std* object has been redirected.

But it's not in that case. Its still logging to my test.log file.

Python version: 3.4.8

Any help would be greatly appreciated.

like image 355
Dawid Fieluba Avatar asked Mar 05 '23 16:03

Dawid Fieluba


1 Answers

The reason sys.__stdout__ did not work is because you replaced the original stdout's file descriptor with os.dup2(), so any Python file object that is based on it would print to the newly-opened file. The old stdout actually gets closed when you do dup2, so there is no restoring it.

If you want to have all Python code that uses sys.stdout to print to /tmp/test.log, open a new file and assign it to sys.stdout.

sys.stdout = open('/tmp/test.log', 'a+')

The original sys.stdout will remain available as sys.__stdout__.

f you want also to redirect any code that writes directly to sys.stdout.fileno(), including subprocesses that you start with os.system() or subprocess.call(), while keeping access to the original stdout, things get more complex: you would need to dup() stdout first and save that, then use your dup2() call to replace FD 1:

saved_stdout_fd = os.dup(sys.stdout.fileno())
saved_stdout = os.fdopen(saved_stdout_fd,'w')
so = open('/tmp/test.log', 'a+')
os.dup2(so.fileno(), sys.stdout.fileno())

Now sys.stdout goes to your /tmp/test.log and saved_stdout will write to the original stdout.

like image 113
Leo K Avatar answered Mar 18 '23 06:03

Leo K