(1) You cannot have interactivity on the tee'd output because it's a regular stream, and not a terminal. A terminal allows to do a ton of things: position the cursor, erase contents, read keys, echo keypresses to the screen, etc. A regular file on a disk can't do all these things, this is why pdb
fails to do these things in interactive mode. You can check that sys.stdout.isatty()
returns True
is you run a REPL.
(2) You can of course change every print
function invocation in your code to write to stdout and to whatever file you want, because you can redefine print
. This works in Python 3, and in Python 2.7 if you from __future__ import print
. Then you can do things like this:
system_print = print # preserve the original.
def print_also_to(other_file):
def tee_print(*args, **kwargs):
system_print(*args, **kwargs) # Normally prints to stdout.
system_print(*args, **kwargs, file=other_file) # Write a copy.
return tee_print
print = print_also_to(open('/tmp/copy-of-stdout')) # A crude example.
print("Hello world!") # Unmodified code.
With print
statements, your situation is worse. Use strace
on Linux or DTrace
on macOS to capture the writing to stdout (and elsewhere) and redirect it to a file when starting your process:
strace -e trace=write -o writes.txt python your-script.py
It will write to the file something like write(1, 'Hello world!')
. You would need to parse it and reconstruct output to stdout (1) specifically to produce a real copy of the output.
I suppose pdb
's interactive mode will work under this, too; at the very least, Python REPL works fine under strace.