How to duplicate sys.stdout to a log file?
Since you're comfortable spawning external processes from your code, you could use tee
itself. I don't know of any Unix system calls that do exactly what tee
does.
# Note this version was written circa Python 2.6, see below for
# an updated 3.3+-compatible version.
import subprocess, os, sys
# Unbuffer output (this ensures the output is in the correct order)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
print "\nstdout"
print >>sys.stderr, "stderr"
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)
You could also emulate tee
using the multiprocessing package (or use processing if you're using Python 2.5 or earlier).
Update
Here is a Python 3.3+-compatible version:
import subprocess, os, sys
tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
# Cause tee's stdin to get a copy of our stdin/stdout (as well as that
# of any child processes we spawn)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())
# The flush flag is needed to guarantee these lines are written before
# the two spawned /bin/ls processes emit any output
print("\nstdout", flush=True)
print("stderr", file=sys.stderr, flush=True)
# These child processes' stdin/stdout are
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)
How to Duplicate/Capture Stdout in Log File with Python
Since it seems you are only interested in exceptions you can use sys.excepthook
instead of that wrappper as explained here: Logging uncaught exceptions in Python
That way it only has to be defined once and you can't forget it when you define new functions.
Making Python loggers output all messages to stdout in addition to log file
All logging output is handled by the handlers; just add a logging.StreamHandler()
to the root logger.
Here's an example configuring a stream handler (using stdout
instead of the default stderr
) and adding it to the root logger:
import logging
import sys
root = logging.getLogger()
root.setLevel(logging.DEBUG)
handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
root.addHandler(handler)
Related Topics
Django Form Dropdown List of Numbers
Unit Testing File Modifications
Fake Serial Communication Under Linux
How to Run Python Script on Terminal (Ubuntu)
Python Tkinter: Attach Scrollbar to Listbox as Opposed to Window
Paramiko Error: Error Reading Ssh Protocol Banner
Multiprocessing.Pool Spawning New Childern After Terminate() on Linux/Python2.7
Using Sudo Inside Jupyter Notebook's Cell
Python: When to Use Pty.Fork() Versus Os.Fork()
Pairing Bluetooth Devices with Passkey/Password in Python - Rfcomm (Linux)
What's the Advantage of Queues Over Pipes When Communicating Between Processes
Create Single Python Executable Module
Python Requests, How to Specify Port for Outgoing Traffic
Importerror: Libtk8.6.So: Cannot Open Shared Object File: No Such File or Directory
Python Valueerror: Embedded Null Byte When Reading Png File from Bash Pipe