To redirect output to a file and a terminal without modifying how your Python script is used outside, you could use pty.spawn(itself)
:
#!/usr/bin/env python
"""Redirect stdout to a file and a terminal inside a script."""
import os
import pty
import sys
def main():
print('put your code here')
if __name__=="__main__":
sentinel_option = '--dont-spawn'
if sentinel_option not in sys.argv:
# run itself copying output to the log file
with open('script.log', 'wb') as log_file:
def read(fd):
data = os.read(fd, 1024)
log_file.write(data)
return data
argv = [sys.executable] + sys.argv + [sentinel_option]
rc = pty.spawn(argv, read)
else:
sys.argv.remove(sentinel_option)
rc = main()
sys.exit(rc)
If pty
module is not available (on Windows) then you could replace it with teed_call()
function that is more portable but it provides ordinary pipes instead of a pseudo-terminal -- it may change behaviour of some programs.
The advantage of pty.spawn
and subprocess.Popen
-based solutions over replacing sys.stdout
with a file-like object is that they can capture the output at a file descriptor level e.g., if the script starts other processes that can also produce output on stdout/stderr. See my answer to the related question: Redirect stdout to a file in Python?