相当于 sys.argv 的点击
Equivalent of sys.argv in click
我在 Python 中使用 click 为我的程序创建 CLI。如果发生异常,我想执行一个函数(下面通过占位符 do_something()
表示),但前提是某个参数通过 CLI 传递(此处:--verbose
或 -v
)。
我知道我可以通过 sys.argv
访问命令行输入。这是我使用这种方法的概念性最小工作示例:
#filename: my_app.py
import click
@click.group()
@click.option('--verbose', '-v', is_flag=True)
def cli():
pass
@click.command()
def greeting():
print('hello world')
raise Exception
@cli.command()
def spam():
print('SPAM')
raise Exception
def do_something():
print('Doing something...')
if __name__ == '__main__':
try:
main()
except e:
if '--verbose' in sys.argv or '-v' in sys.argv:
do_something()
raise e
尽可能准确:如果任何子命令出现异常,我希望程序在 --verbose
标志打开时 do_something()
,但如果它不是离开。例如。对于 greeting
子命令,CLI 的行为应如下所示:
~$ python my_app.py --verbose greeting
hello world
Doing something...
Exception
~$ python my_app.py greeting
hello world
Exception
虽然上面显示的 sys.argv
解决方案有效,但如果我可以使用 click 的内部名称(在本例中为 'verbose'
)引用命令行选项,那就太好了。也就是说,我想在这里做这样的事情:
...
if __name__ == '__main__':
try:
main()
except e:
if 'verbose' in click.argv:
do_something()
raise e
这是click提供的功能吗?
如果我错了请纠正我,但在我看来你希望能够在出现异常的情况下输出更多information/clean。
您可以尝试以下几种选择:
- 将 try/except 逻辑移动到利用
verbose
标志的 greeting
方法中,并在那里调用 do_something
- Consider looking at callbacks 看看你是否可以利用这些来做你想做的事。如果
do_something
没有更多上下文,我无法确定它是否是回调的良好用例。
- 最接近您的问题的是拥有一个全局范围变量
_verbose
,如下例所示:
import click
global _verbose
_verbose = False
def do_something():
print(f'Doing something')
@click.group()
def cli():
pass
@cli.command()
@click.option('--verbose', '-v', is_flag=True)
def greeting():
global _verbose
_verbose = verbose
if verbose:
print('hello world')
raise Exception("Test")
else:
print('hello')
@cli.command()
@click.option('--count', '-c')
def spam(count):
print(count * 'SPAM')
if __name__ == '__main__':
try:
cli()
except Exception as e:
if _verbose:
do_something()
raise e
我已经用一个工作片段更新了我的答案,该片段不依赖全局变量来执行此操作,而是利用 Python 的 pass-by-reference
和 click 的高级上下文示例
import click
def do_something():
print(f'Doing something')
@click.group()
@click.option('--verbose', '-v', is_flag=True)
@click.pass_context
def cli(ctx, verbose):
ctx.obj['verbose'] = verbose
pass
@cli.command()
@click.pass_context
def greeting(ctx):
if ctx.obj['verbose']:
print('hello world')
raise Exception("Test")
else:
print('hello')
@cli.command()
@click.option('--count', '-c')
def spam(count):
print(count * 'SPAM')
if __name__ == '__main__':
flags = {}
try:
cli(obj=flags)
except Exception as e:
if flags['verbose']:
do_something()
raise e
我在 Python 中使用 click 为我的程序创建 CLI。如果发生异常,我想执行一个函数(下面通过占位符 do_something()
表示),但前提是某个参数通过 CLI 传递(此处:--verbose
或 -v
)。
我知道我可以通过 sys.argv
访问命令行输入。这是我使用这种方法的概念性最小工作示例:
#filename: my_app.py
import click
@click.group()
@click.option('--verbose', '-v', is_flag=True)
def cli():
pass
@click.command()
def greeting():
print('hello world')
raise Exception
@cli.command()
def spam():
print('SPAM')
raise Exception
def do_something():
print('Doing something...')
if __name__ == '__main__':
try:
main()
except e:
if '--verbose' in sys.argv or '-v' in sys.argv:
do_something()
raise e
尽可能准确:如果任何子命令出现异常,我希望程序在 --verbose
标志打开时 do_something()
,但如果它不是离开。例如。对于 greeting
子命令,CLI 的行为应如下所示:
~$ python my_app.py --verbose greeting
hello world
Doing something...
Exception
~$ python my_app.py greeting
hello world
Exception
虽然上面显示的 sys.argv
解决方案有效,但如果我可以使用 click 的内部名称(在本例中为 'verbose'
)引用命令行选项,那就太好了。也就是说,我想在这里做这样的事情:
...
if __name__ == '__main__':
try:
main()
except e:
if 'verbose' in click.argv:
do_something()
raise e
这是click提供的功能吗?
如果我错了请纠正我,但在我看来你希望能够在出现异常的情况下输出更多information/clean。
您可以尝试以下几种选择:
- 将 try/except 逻辑移动到利用
verbose
标志的greeting
方法中,并在那里调用do_something
- Consider looking at callbacks 看看你是否可以利用这些来做你想做的事。如果
do_something
没有更多上下文,我无法确定它是否是回调的良好用例。 - 最接近您的问题的是拥有一个全局范围变量
_verbose
,如下例所示:
import click
global _verbose
_verbose = False
def do_something():
print(f'Doing something')
@click.group()
def cli():
pass
@cli.command()
@click.option('--verbose', '-v', is_flag=True)
def greeting():
global _verbose
_verbose = verbose
if verbose:
print('hello world')
raise Exception("Test")
else:
print('hello')
@cli.command()
@click.option('--count', '-c')
def spam(count):
print(count * 'SPAM')
if __name__ == '__main__':
try:
cli()
except Exception as e:
if _verbose:
do_something()
raise e
我已经用一个工作片段更新了我的答案,该片段不依赖全局变量来执行此操作,而是利用 Python 的 pass-by-reference
和 click 的高级上下文示例
import click
def do_something():
print(f'Doing something')
@click.group()
@click.option('--verbose', '-v', is_flag=True)
@click.pass_context
def cli(ctx, verbose):
ctx.obj['verbose'] = verbose
pass
@cli.command()
@click.pass_context
def greeting(ctx):
if ctx.obj['verbose']:
print('hello world')
raise Exception("Test")
else:
print('hello')
@cli.command()
@click.option('--count', '-c')
def spam(count):
print(count * 'SPAM')
if __name__ == '__main__':
flags = {}
try:
cli(obj=flags)
except Exception as e:
if flags['verbose']:
do_something()
raise e