In Click, Context.with_resource
‘s documentation states it can be used to:
[r]egister a resource as if it were used in a
with
statement. The resource will be cleaned up when the context is popped.
From this, I understand that the context manager that I pass to Context.with_resource
will be exited after execution of the root CLI group and any of its sub-groups and commands. This seems to work fine with an example such as this, where I am redirecting stdout
to a file:
import contextlib
import click
@contextlib.contextmanager
def my_redirect_stdout(file):
with open(file, mode="w") as fp:
with contextlib.redirect_stdout(fp):
yield
@click.group()
@click.pass_context
@click.argument("file")
def cli(ctx, file):
ctx.with_resource(my_redirect_stdout(file))
@cli.command()
def hello():
print(f"this goes to a file")
if __name__ == "__main__":
cli()
However, this does not work when I try to capture exception tracebacks in the following way:
import contextlib
import sys
import traceback
import click
@contextlib.contextmanager
def capture_traceback(file):
with open(file, mode="w") as fp:
try:
yield
except:
print(f"exception!")
traceback.print_exc(file=fp)
sys.exit(1)
@click.group()
@click.pass_context
@click.argument("file")
def cli(ctx, file):
ctx.with_resource(capture_traceback(file))
@cli.command()
def hello():
raise ValueError("error!")
if __name__ == "__main__":
cli()
The exception does not seem to be caught within the capture_traceback
function. Instead, it is printed by the interpreter as usual. It seems as though Click is catching the error, closing the context manager, and then re-raising. How can I catch exceptions from any group or command, print the traceback to a file, and exit the program (without printing the traceback to the terminal/stderr
)?