In the case where there are command groups and every sub-command may raise exceptions, how can I handle them all together in one place?
Given the example below:
import click@click.group()
def cli():pass@cli.command()
def foo():passif __name__ == '__main__':cli()
Both cli
and foo
may raise. I know that one possible solution is to place try-except
around cli()
in the if
clause. But that does not work when you distribute a package. In setup.py, you have to specify an entry point (in this case, cli
). The if
clause will not be executed.
You can create a custom click.Group
by inheriting from same. The custom group can be used by passing it as the cls
parameter to the click.group()
decorator. If you override the __call__
method, you can insert an exception handler like:
Code:
class CatchAllExceptions(click.Group):def __call__(self, *args, **kwargs):try:return self.main(*args, **kwargs)except Exception as exc:click.echo('We found %s' % exc)
Test Code:
import click@click.group(cls=CatchAllExceptions)
def cli():pass@cli.command()
def foo():raise Exception('an exception!')if __name__ == '__main__':cli('foo'.split())
Results:
We found an exception!