I have a basic logger handler in Python setup to log to a file. I want this log handler to log any/all stdout or stderr messages that would ordinarily be printed to the console, but I don't want to redirect or capture it. In other words, I still want everything to be printed in the usual way.
The use case here is that I don't want to wrap each and every command in my application with
try:
do_something_that_could_raise_exception()
except Exception as e:
logger.exception(e)
Instead, I just want to let the application run, and be able to look in the log file to see a stack trace from any errors that are encountered. I just want all stdout/stderr messages to also appear in my log file.
This seems like a twist on a topic that has been asked many times on SO. I've read Logging Python stdout to File... with active stdout (backspacing/updating), Redirect stdout to a file in Python?, and many others, but those don't seem to address the situation I have. All the questions I've seen talk about how to use multiple handlers to print to both a log and stdout, or how to redirect stdout to the log such that nothing is displayed in the terminal.
EDIT
Editing for posterity. After some more searching I found https://code.tutsplus.com/tutorials/professional-error-handling-with-python--cms-25950, which demonstrates how to add a function decorator that will direct exceptions to a given logging handler. This isn't quite as concise as I was hoping (since I still have to add the function decorator to all my function definitions), but it is quite a bit less verbose than wrapping all my function calls in try-except.
def log_error(logger)
def decorated(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
if logger:
logger.exception(e)
raise
return wrapped
return decorated
Here is how to use it:
01
02
03
04
05
06
07
08
09
10
11
import logging
logger = logging.getLogger()
@log_error(logger)
def f():
raise Exception('I am exceptional')