[英]Can I have a main() Click function that invokes all other sub-commands?
我有一個像這樣的腳本:
#myscript.py
import click
def step1(arg1):
print('Step 1: ' + arg1)
def step2(arg2):
print('Step 2: ' + arg2)
def main(arg1, arg2):
step1(arg1)
step2(arg2)
大多數時候,我想使用myscript arg1 arg2
運行腳本,但偶爾我可能只想運行一個步驟:例如myscript step1 arg1
。 如何設置點擊操作? 有沒有辦法擁有一個默認命令,然后再擁有其他可選命令?
這似乎是Click不鼓勵的一件事 :
有時,從另一個命令調用一個命令可能很有趣。 單擊通常不建議使用這種模式,但是還是可以的。
我需要使用這種click.invoke()
模式嗎?
我認為多命令鏈接和多命令管道功能旨在解決這種情況。 流水線提供了所請求的確切行為(在命令行中未給出任何命令時,都會調用step1
和step2
),但是它更加冗長,並且使用chain=True
任何參數都不是可選的。 您必須(a)始終同時給出arg1
和arg2
,即使僅調用step2
; 或(b)將這些參數轉換為選項( --arg1 foo
而不是foo
)。
import click
@click.group(chain=True)
def cli():
pass
@cli.command()
@click.argument('arg1')
def step1(arg1):
click.echo('Step 1: ' + arg1)
@cli.command()
@click.argument('arg2')
def step2(arg2):
click.echo('Step 2: ' + arg2)
cli()
然后:
$ python3 chain.py step1 foo step2 bar
Step 1: foo
Step 2: bar
$ python3 chain.py step2 bar
Step 2: bar
import click
@click.group(chain=True, invoke_without_command=True)
@click.argument('arg1')
@click.argument('arg2')
def cli(arg1, arg2):
pass
@cli.resultcallback()
def process_pipeline(processors, **kwargs):
# If no commands given, invoke step1 then step2
processors = processors if len(processors) else [step1, step2]
for processor in processors:
processor(**kwargs)
def step1(**kwargs):
click.echo('Step 1: ' + kwargs['arg1'])
def step2(**kwargs):
click.echo('Step 2: ' + kwargs['arg2'])
@cli.command('step1')
def make_step1():
return step1
@cli.command('step2')
def make_step2():
return step2
cli()
然后
$ python3 pipeline.py foo bar
Step 1: foo
Step 2: bar
$ python3 pipeline.py foo bar step2
Step 2: bar
我沒有用這個問題來表達我要嘗試做的事情,因為每一步都需要前一步的輸出。 非常感謝Paul帶領我走上正確的道路。
我的解決方案是這樣的:
@click.group(invoke_without_command=True)
@click.option('--arg1')
@click.option('--arg2')
@click.pass_context
def cli(ctx, arg1, arg2):
'''Description
'''
if ctx.invoked_subcommand is None:
do_everything(ctx, arg1, arg2)
@cli.command()
@click.option('--arg1')
def step_1(arg1):
return do_something(arg1)
@cli.command()
@click.argument('step_one_result')
@click.option('--arg2')
def step_2(step_one_result, arg2):
do_something_else(step_one_result, arg2)
def do_everything(ctx, arg1, arg2):
step_one_result = ctx.invoke(step_1, arg1=arg1)
ctx.invoke(do_something_else, step_one_result=step_one_result, arg2=arg2)
#and because of weirdness with pass_context and using setuptools
def main():
cli(obj={})
if __name__ == '__main__':
main()
編輯:您會注意到使用ctx.invoke()
來調用函數,而不會出現以下錯誤
line 619, in make_context
ctx = Context(self, info_name=info_name, parent=parent, **extra)
TypeError: __init__() got an unexpected keyword argument 'arg1'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.