标签: python-click

如何使用 click.prompt 从用户那里获取有效日期?

你好,

我实际上正在学习如何使用点击包中的一些元素,并且我希望能够使用该prompt命令从用户那里获取有效日期。

我尝试查找文档,并在http://click.pocoo.org/5/prompts/下找到了这个:

要手动请求用户输入,可以使用prompt()函数。默认情况下,它接受任何 Unicode 字符串,但您可以要求任何其他类型。

所以我编写了这段代码并尝试将类 datetime.datetime 作为所需的输入类型传递:

import datetime

value = click.prompt("Enter a date", type=datetime.datetime)
Run Code Online (Sandbox Code Playgroud)

当我执行此代码时,会出现提示,但在插入有效日期并按 Enter 键后,我收到此错误消息:

回溯(最近一次调用):文件“”,第 1 行,文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/click/termui.py”,第 98 行,在提示 result = value_proc(value) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/click/types.py",第 38 行,在调用 return self.convert (value, param, ctx) 文件“/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/click/types.py”,第 87 行,在转换中返回 self.func(value )类型错误:需要一个整数(得到类型 str)

请您告诉我我在这段代码中做错了什么吗?

基本上我想通过编写类似这段(部分虚构的)代码的内容来获得正确格式化的日期值:

import datetime

value = click.prompt("Enter a date", 
                     type=datetime.datetime,
                     format="%d/%m/%Y",
                     default=datetime.datetime.now())
Run Code Online (Sandbox Code Playgroud)

非常感谢

python python-click

4
推荐指数
1
解决办法
2763
查看次数

点击类型转换

我用来click定义一个 CLI,它采用datetimes 和逗号分隔的参数列表。

import click

def valid_date(s):
    try:
        return dt.strptime(s, "%Y-%m-%d")
    except ValueError:
        msg = "Not a valid date: '{0}'.".format(s)
        raise Exception(msg)
    except TypeError:
        return None

split_parameter = lambda _, __, s: s.split(",")
check_date = lambda _, __, s: valid_date(s)


@click.command()
@click.argument('symbols', callback=split_parameter)
@click.option('--start_date', callback=check_date)
@click.option('--end_date', callback=check_date)
@click.option('--file_name')
def f(symbols, start_date, end_date, file_name):
     return None
Run Code Online (Sandbox Code Playgroud)

它有效,但 s 周围的逻辑callback有点尴尬。拆分列表和转换都datetime中断了单击的简单结构。有没有一种Python式的方法可以做到这一点?

python command-line-interface python-click

4
推荐指数
1
解决办法
4184
查看次数

单击命令中的可选参数

我正在尝试用Click完成CLI解析方面不是很标准的事情,并且只能部分工作:

  • 主CLI有多个子命令(在“显示”和“检查”下面的示例中)
  • 这两个命令都可能具有可选参数,但是该参数在它们之前而不是之后
  • 我决定在“上方”组中处理该参数,并在上下文中传递值

样品:

import click

@click.group()
@click.argument('hostname', required=False)
@click.pass_context
def cli(ctx, hostname=None):
    """"""
    ctx.obj = hostname
    click.echo("cli: hostname={}".format(hostname))

@cli.command()
@click.pass_obj
def check(hostname):
    click.echo("check: hostname={}".format(hostname))

@cli.command()
@click.pass_obj
def show(hostname):
    click.echo("check: hostname={}".format(hostname))

if __name__ == '__main__':
    cli()
Run Code Online (Sandbox Code Playgroud)

具有主机名的部分起作用:

> pipenv run python cli.py  localhost check
cli: hostname=localhost
check: hostname=localhost
> pipenv run python cli.py  localhost show
cli: hostname=localhost
check: hostname=localhost
Run Code Online (Sandbox Code Playgroud)

但是没有主机名的那部分却没有:

> pipenv run python cli.py show
Usage: cli.py [OPTIONS] [HOSTNAME] COMMAND [ARGS]...

Error: Missing command.
Run Code Online (Sandbox Code Playgroud)

有人对我应该开始研究的方向有所了解吗?

python python-click

4
推荐指数
1
解决办法
6971
查看次数

python click子命令统一错误处理

如果有命令组并且每个子命令都可能引发异常,我如何在一个地方一起处理它们?

鉴于以下示例:

import click


@click.group()
def cli():
    pass

@cli.command()
def foo():
    pass

if __name__ == '__main__':
    cli()
Run Code Online (Sandbox Code Playgroud)

双方clifoo可能会提高。我知道,一个可能的解决方案是将try-except各地cli()的在if条款。但是当你分发一个包时这不起作用。在setup.py 中,您必须指定一个入口点(在本例中为cli)。该if条款将不会被执行。

python python-click

4
推荐指数
1
解决办法
1257
查看次数

我可以给点击选项另一个名字吗?

我用click这样的:

import click

@click.command(name='foo')
@click.option('--bar', required=True)
def do_something(bar):
    print(bar)
Run Code Online (Sandbox Code Playgroud)

因此选项的名称和函数参数的名称是相同的.当它不相同时(例如,当你想要--id而不是--bar)时,我得到:

TypeError: do_something() got an unexpected keyword argument 'id'
Run Code Online (Sandbox Code Playgroud)

我不希望调用该参数,id因为这是一个Python函数.我不希望将CLI参数调用为不同,因为它会更麻烦/更不直观.我该如何解决?

python command-line-interface python-click

4
推荐指数
1
解决办法
593
查看次数

动态指定选项和参数

我想从数据库加载参数和选项。我允许用户定义他们自己的选项和参数。用户可以在命令行上调用远程 api。它们指定到终点的 URL 和参数。这是来自数据库的数据的样子

[
    {
        "name": "thename1",
        "short": "a",
        "long": "ace"
        "type": "string",
        "required": false
    },
    {
        "name": "thename2",
        "short": "b",
        "long": "bravo"
        "type": "number",
        "required": true
    },
    {
        "name": "thename3",
        "short": "c",
        "long": "candy"
        "type": "array",
        "required": true
    }
]
Run Code Online (Sandbox Code Playgroud)

这些参数与远程端点的需要一致。每个 API 端点都有不同的参数,因此它们需要是动态的。这是命令行的外观。

command run www.mysite.com/api/get -a testparam --bravo testpara2 -c item1 item2
Run Code Online (Sandbox Code Playgroud)

参数和值将映射到 URL 中。有没有办法在点击中设置动态参数?

python command-line-interface python-click

4
推荐指数
1
解决办法
2141
查看次数

使用 Python Click 扩展 BASH 完成

我想自定义我的 Python Click CLI 程序的 BASH 完成功能,不仅包括脚本的命令/子命令,还包括脚本创建的对象。

假设我的程序被调用cli-tool,它可以foo使用以下命令创建对象:

cli-tool object create foo
Run Code Online (Sandbox Code Playgroud)

为简单起见,假设该命令只是将参数字符串(foo在本例中)连接到位于~/.cli-tool/objects/foo. 这样做cat ~/.cli-tool/objects/foo,然后将打印foo在你的终端。

我希望该工具做的是当我输入:

cli-tool object get <TAB><TAB>
Run Code Online (Sandbox Code Playgroud)

终端然后将名单foo及任何其他文件里面住~/.cli-tool/objects

作为记录,我已阅读Python Click 6.x stable 文档,其中明确指出:

目前,Bash 补全是一个不可定制的内部功能。这在未来的版本中可能会放宽。

我希望有一种方法可以从以下命令中提取完整的BASH 完成脚本:

eval "$(_CLI_TOOL_COMPLETE=source cli-tool)"
Run Code Online (Sandbox Code Playgroud)

然后自己定制。我也看过点击完成项目,但我不确定它除了扩展 Zsh 和 Fish shell 的完成之外还有什么作用。

有没有人达到我上面提到的完成类型?

command-line-interface bash-completion python-click

4
推荐指数
1
解决办法
3619
查看次数

是否可以在 Python Click 中动态生成命令

我正在尝试click从配置文件生成命令。本质上,这种模式:

import click

@click.group()
def main():
    pass

commands = ['foo', 'bar', 'baz']
for c in commands:
    def _f():
        print("I am the '{}' command".format(c))
    _f = main.command(name=c)(_f)

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

--help文本看起来不错:

Usage: test_click.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  bar
  baz
  foo
Run Code Online (Sandbox Code Playgroud)

但是,所有命令似乎都路由到生成的最后一个命令:

$ ./test_click.py foo
I am the 'baz' command
$ ./test_click.py bar
I am the 'baz' command
$ ./test_click.py baz
I am the 'baz' command
Run Code Online (Sandbox Code Playgroud)

我正在尝试的实际上可能吗?

python python-click

4
推荐指数
1
解决办法
1647
查看次数

我可以使用上下文值作为 click.option() 默认值吗?

我想在我的配置中使用一个值(我加载到我的上下文中)作为单击命令选项的默认值。我已经阅读了文档的这一部分,但我认为我不明白我需要做什么。

这是我的示例脚本:

import sys
import click

@click.group()
@click.pass_context
def cli(ctx):
    """
    CLI
    """
    ctx.ensure_object(dict)
    ctx.obj['DEFAULT_ENVIRONMENT'] = "dev"


@cli.command()
@click.option('-e', '--environment', required=True, default=click.get_current_context().obj['DEFAULT_ENVIRONMENT'])
def show_env(environment):
    click.echo(environment)


if __name__ == '__main__':
    cli()
Run Code Online (Sandbox Code Playgroud)

如果我运行python cli.py show-env,目标是让它输出dev(因为我没有传递参数,因为它是从上下文加载的)。

这失败了

Traceback (most recent call last):
  File "testcli.py", line 15, in <module>
    @click.option('-e', '--environment', required=True, default=click.get_current_context().obj['DEFAULT_ENVIRONMENT'])
  File "/home/devuser/.virtualenvs/cli/lib/python3.6/site-packages/click/globals.py", line 26, in get_current_context
    raise RuntimeError('There is no active click context.')
RuntimeError: There is no active click context.
Run Code Online (Sandbox Code Playgroud)

我也尝试过@pass_context在我的show_env命令上使用,如下所示: …

python command-line-interface python-click

4
推荐指数
1
解决办法
1438
查看次数

测试 Python Click 命令异常

我正在尝试通过使用Click 包实现的命令来测试异常的引发。

这是我的命令:

@click.option(
    '--bucket_name',
...)
@click.option(
    '--group_id',
...)
@click.option(
    '--artifact_id',
...)
@click.option(
    '--version',
...)
@click.option(
    '--artifact_dir',
    required=False,
    default='downloads/artifacts/',
...)
@click.command()
def download_artifacts(
    bucket_name,
    group_id, artifact_id, version,
    artifact_dir
):
    logger.info(
        f"bucket_name: {bucket_name}, "
        f"group_id: {group_id}, "
        f"artifact_id: {artifact_id}, "
        f"version: {version}, "
        f"artifact_dir: {artifact_dir}, "
        )

    if not artifact_dir.endswith('/'):
        raise ValueError(
            "Enter artifact_dir ending with '/' ! artifact_dir: "
            f"{artifact_dir}")
...
Run Code Online (Sandbox Code Playgroud)

这是我的测试代码,assertRaises它不起作用:

def test_download_artifacts_invalid_dir(
        self,
    ):
        runner = CliRunner()
        with self.assertRaises(ValueError):
            result = runner.invoke(
                download_artifacts,
                '--bucket_name my_bucket …
Run Code Online (Sandbox Code Playgroud)

python command-line-interface python-unittest python-click

4
推荐指数
1
解决办法
3852
查看次数