Python单击:setuptools下的异常处理

Python单击:setuptools下的异常处理,python,exception-handling,setuptools,python-click,Python,Exception Handling,Setuptools,Python Click,我有一个运行良好的应用程序,但我希望在用户键入未知命令时收到通知。例如,如果mycli foo有效,但它们键入mycli bar,我希望覆盖默认的异常处理行为,并向错误跟踪器(如rollbar)发出错误 我找到了一个描述如何重写异常处理的函数,但它假定我有一个命令。我遇到的问题是,我还通过以下方式与setuptools集成,它指向[console\u scripts]部分中的命令。例如,yourscript=yourscript:cli指向cli命令 我不知道如何从[console\u scri

我有一个运行良好的应用程序,但我希望在用户键入未知命令时收到通知。例如,如果
mycli foo
有效,但它们键入
mycli bar
,我希望覆盖默认的异常处理行为,并向错误跟踪器(如rollbar)发出错误

我找到了一个描述如何重写异常处理的函数,但它假定我有一个
命令
。我遇到的问题是,我还通过以下方式与setuptools集成,它指向
[console\u scripts]
部分中的
命令。例如,
yourscript=yourscript:cli
指向
cli
命令


我不知道如何从
[console\u scripts]
中调用
cli.main()
,或者这是否是正确的想法。

通过自定义
单击.Command
类,您可以捕获调用命令行,然后使用自定义类在异常处理程序中报告命令行中的任何错误,如:

自定义类 使用自定义类 然后,要使用自定义命令/组,请将其作为
cls
参数传递给
click.command
click.group
装饰器,例如:

@click.command(cls=CatchAllExceptions(click.Command, handler=report_exception))

@click.group(cls=CatchAllExceptions(click.Group, handler=report_exception))

@click.group(cls=CatchAllExceptions(click.MultiCommand, handler=report_exception))
请注意,需要指定所需的
click.Command
子类以及 要将异常信息发送到的处理程序

这是怎么回事? 这是因为click是一个设计良好的OO框架。
@click.group()
@click.command()
装饰程序通常实例化
click.group
click.command
对象,但允许使用
cls
参数过度处理此行为。因此,在我们自己的类中继承
click.Command
(etc)并超越所需的方法是一件相对容易的事情

在本例中,我们跳过
单击.Command.make_context()
以获取原始命令行,然后
单击.Command.invoke()
以捕获异常,然后调用异常处理程序

测试代码: 结果:
开箱即用!非常感谢。
@click.command(cls=CatchAllExceptions(click.Command, handler=report_exception))

@click.group(cls=CatchAllExceptions(click.Group, handler=report_exception))

@click.group(cls=CatchAllExceptions(click.MultiCommand, handler=report_exception))
import click

@click.group(cls=CatchAllExceptions(click.Group, handler=report_exception))
def cli():
    """A wonderful test program"""
    pass

@cli.command()
def foo():
    """A fooey command"""
    click.echo('Foo!')


if __name__ == "__main__":
    commands = (
        'foo',
        'foo --unknown',
        'foo still unknown',
        '',
        '--help',
        'foo --help',
    )

    import sys, time

    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for cmd in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + cmd)
            time.sleep(0.1)
            cli(cmd.split())

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise
Click Version: 6.7
Python Version: 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> foo
Foo!
-----------
> foo --unknown
Error: no such option: --unknown
:: Command line: test.py foo --unknown
:: Raised error: no such option: --unknown
-----------
> foo still unknown
:: Command line: test.py foo still unknown
:: Raised error: Got unexpected extra arguments (still unknown)
Usage: test.py foo [OPTIONS]

Error: Got unexpected extra arguments (still unknown)
-----------
> 
Usage: test.py [OPTIONS] COMMAND [ARGS]...

  A wonderful test program

Options:
  --help  Show this message and exit.

Commands:
  foo  A fooey command
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...

  A wonderful test program

Options:
  --help  Show this message and exit.

Commands:
  foo  A fooey command
-----------
> foo --help
Usage: test.py foo [OPTIONS]

  A fooey command

Options:
  --help  Show this message and exit.