Search code examples
pythonexceptionstdoutstderr

Why is Exception output not captured by contextlib.redirect_stderr context manager?


In the following code, I would have expected the exception output and traceback to be written to test.txt file, but that does not happen.

import contextlib

with open("test.txt", "a") as f:
    with contextlib.redirect_stderr(f):
        raise Exception("Hello")

Why is it not working as expected and how can I correctly redirect the exception output to a file?


Solution

  • Because redirecting sys.stderr doesn't catch exceptions in python (it would be bad if it did, right? Because exceptions are only supposed to be caught by try/except blocks.) so the exception handling code interrupts your running code (and the redirect).

    Proof:

    import contextlib
    from sys import stderr
    
    with open("test.txt", "a") as f:
        with contextlib.redirect_stderr(f):
            sys.stderr.write("hello")
            sys.stderr.flush()
    

    writes correctly.

    To redirect the output from all exceptions to a file you have two options: catch all exceptions globally in a try/except block and do the writing yourself, or use shell redirection to send the script's stderr to a file, with something like

    python my_script.py 2>errors.txt
    

    If you want to do it yourself, see this question for discussion of getting the traceback.