python click 参数检测与子命令
目录
参数检测
click 在设置参数时可以使用 type 指定参数类型,可以使用 python 内置类型和 click 内置的类型,例如
@click.command()
@click.option('--pos', nargs=2, type=float)
def findme(pos):
click.echo('%s / %s' % pos)
为了更精确地控制参数格式,click 也支持自定义参数类型。用户可以继承 click.ParamType 类,并实现 convert 方法。
class StartTimeParamType(click.ParamType):
name = "start_time"
def convert(self, value, param, ctx):
try:
if len(value) != 10:
self.fail("length of start_time must be 10".format(value=value))
start_date_time = datetime.datetime.strptime(value, "%Y%m%d%H")
return start_date_time
except ValueError:
self.fail("{value} is not a valid start_time".format(value=value)
子命令
通常有两种形式实现子命令:
- 类似 git 命令,通过第二个关键词区分不同的命令
git clone
git add
- 类似 ecflow_client 命令,不同的参数实现不同的功能
ecflow_client --load
ecflow_client --help
click 中的 group command 可以很方便地实现第一种形式的命令。
对于第二种方式,可以使用 click 中的 eager options 折中实现。
eager option 比一般option具有更高的优先级,解析命令时,click 会首先处理 eager 参数。我们可以为 eager 参数设置 callback,在处理该参数时会调用 callback 函数。如果在callback 函数中退出命令,就可以实现子命令功能。
def show_find_local_file_types(ctx, param, value):
if not value:
return
if 'config_dir' in ctx.params:
config_dir = ctx.params['config_dir']
config_dir = Path(config_dir).absolute()
else:
config_dir = get_default_local_config_path()
click.echo("config dir:{config_dir}".format(config_dir=str(config_dir)))
click.echo("data types:")
for a_config_file in sorted(config_dir.rglob("*.yml")):
click.echo(a_config_file.relative_to(config_dir).with_suffix(''))
ctx.exit(0)
@click.command(short_help="Find local data path.")
@click.option("--config-dir", is_eager=True,
help="Config dir, default: {file_path}".format(file_path=str(get_default_local_config_path())))
@click.option("--data-type", required=True,
help="Data type used to locate config file path in config dir.")
@click.option("--show-types", is_flag=True, default=False,
is_eager=True, callback=show_find_local_file_types,
help="Show supported data types defined in config dir and exit.")
@click.argument("start_time", metavar='<start_time>', type=StartTimeParamType())
@click.argument("forecast_time", metavar='<forecast_time>', type=ForecastTimeParamType())
def find_local_file(config_dir, show_types, data_type, start_time, forecast_time):
"""Find local data path using config files in config dir.
start_time: YYYYMMDDHH, such as 2018080100
forecast_time: FFF, such as 000
"""
if config_dir is None:
config_dir = get_default_local_config_path()
config_file_path = find_config(config_dir, data_type)
if config_file_path is None:
click.echo('model data type config not found.', err=True)
click.get_current_context().exit(10)
config = load_config(config_file_path)
file_path = find_file(config, start_time, forecast_time)
click.echo(file_path)
上述示例在一般情况下会执行 find_local_file 函数,但当用户设置了–show-types参数后,会首先执行该参数的 callback 函数 show_find_local_file_types,而该函数中调用 ctx.exit(0) 退出程序,因此 find_local_file 不会被执行。这样就可以通过指定不同的参数改变程序的运行流程。