如何在点击选项中使用 python-click 参数(检查文件中是否存在变量)?

How can I use an python-click argument from within a click option (check if variable exists in file)?

我想传递一个文件(netCDF 数据文件)作为第一个参数和一个选项 (-v) 来指示要从该文件读取到我的脚本的变量。

我想我需要一个自定义回调来评估这个或这些变量 is/are 是否包含在文件中。但是,我无法弄清楚如何从我的回调方法中访问参数。

import click
import xarray as xr

def validate_variable(ctx, param, value):
    """Check that requested variable(s) are in netCDF file """

    # HOW TO ACCESS ARGUMENT 'tile' ???

    with xr.open_dataset(ctx.tile) as ds:
        for v in value:
            if v not in ds.data_vars:
                raise click.BadParameter('Var %s not in file %s.' % (v, ctx.tile))

EPILOG = 'my script ...'

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])

@click.command(context_settings=CONTEXT_SETTINGS, epilog=EPILOG)

@click.pass_context
@click.option('--variable', '-v', multiple=True, metavar='VAR', 
                callback=validate_variable,
                help='variable to render')
@click.argument('tile', type=click.File())
def cli(tile, variable):
    main(tile, variable)

您 运行 在回调中尝试执行此操作时遇到了问题,因为调用回调的顺序并不能保证您需要的所有参数都会在您的回调被评估时得到评估已调用。

您可以执行此操作的一种方法是覆盖 click.Command.make_context(),并在上下文构造完成后进行验证。

自定义命令Class

此函数传递了一个验证器函数,并且 return 是一个自定义 click.Command class。

def command_validate(validator):

    class CustomClass(click.Command):

        def make_context(self, *args, **kwargs):
            ctx = super(CustomClass, self).make_context(*args, **kwargs)
            validator(ctx)
            return ctx

    return CustomClass

验证器函数

验证器函数被传递了一个上下文,并且可以在验证失败时引发 click.BadParameter 异常。

def validate_variables(ctx):
    """Check that requested variable(s) are in netCDF file """

    value = ctx.params['variable']
    tile = ctx.params['tile']
    with xr.open_dataset(tile) as ds:
        for v in value:
            if v not in ds.data_vars:
                raise click.BadParameter(
                    'Var %s not in file %s.' % (v, tile), ctx)

使用自定义 Class:

要使用自定义 class,传递 command_validate 验证器函数,并将 return 值作为 cls 传递给命令装饰器,例如:

@click.command(cls=command_validate(validate_variables), ...OtherOptions...)
...Other config...