如何在 python `click` 中指定 3 个必需选项

发布于 2025-01-12 05:05:53 字数 1832 浏览 2 评论 0原文

我正在尝试使用 https://click.palletsprojects.com/en/8.0。 x/options/

我有一个用例,其中这 3 个参数之一必须是必填字段。

我就是这样做的。

10:45 $ python 测试.py 用法:test.py [OPTIONS]

错误:必须指定 --foo 或 bar 或 car

import click

@click.command()
@click.option('--foo', help='foo is bar.')
@click.option('--count', help='Number of greetings.')
@click.option('--name',
              help='The person to greet.')
def hello(foo, count, name):
    if not (count or name or foo):
        raise click.UsageError( 'Must specify --foo or bar or car')
    
    
    click.echo(f"Hello {name}!")

if __name__ == '__main__':
    hello()

有没有办法将这些参数之一显示为必填字段。像这样的:

python test.py --help
Usage: test.py [OPTIONS]

Options:
  --foo TEXT    foo is bar
 or --count TEXT  Number of greetings
 or  --name TEXT   The person to greet [required]

  --help        Show this message and exit.

尝试 1:

https://click.palletsprojects。 com/en/8.0.x/options/#feature-switches

import click

@click.command()
@click.option('--foo', flag_value='foo', required=True, help='foo is bar.')
@click.option('--count', flag_value='count', required=True, help='Number of greetings.')
@click.option('--name', flag_value='name', required=True, help='The person to greet.')
def hello(foo, count, name):
    if not (count or name or foo):
        raise click.UsageError( 'Must specify --foo or bar or car')
    if foo:
        click.echo(f"Hello {foo}!")
    if count:
        click.echo(f"Hello {count}!")
    if name:
        click.echo(f"Hello {name}!")

if __name__ == '__main__':
    hello()

I am trying to use https://click.palletsprojects.com/en/8.0.x/options/

I have a use case where one out of these 3 parameters has to be a required field.

This is how I am doing it.

10:45 $ python test.py
Usage: test.py [OPTIONS]

Error: Must specify --foo or bar or car

import click

@click.command()
@click.option('--foo', help='foo is bar.')
@click.option('--count', help='Number of greetings.')
@click.option('--name',
              help='The person to greet.')
def hello(foo, count, name):
    if not (count or name or foo):
        raise click.UsageError( 'Must specify --foo or bar or car')
    
    
    click.echo(f"Hello {name}!")

if __name__ == '__main__':
    hello()

Is there a way to show one of these params as required field. something like this:

python test.py --help
Usage: test.py [OPTIONS]

Options:
  --foo TEXT    foo is bar
 or --count TEXT  Number of greetings
 or  --name TEXT   The person to greet [required]

  --help        Show this message and exit.

Try 1:

https://click.palletsprojects.com/en/8.0.x/options/#feature-switches

import click

@click.command()
@click.option('--foo', flag_value='foo', required=True, help='foo is bar.')
@click.option('--count', flag_value='count', required=True, help='Number of greetings.')
@click.option('--name', flag_value='name', required=True, help='The person to greet.')
def hello(foo, count, name):
    if not (count or name or foo):
        raise click.UsageError( 'Must specify --foo or bar or car')
    if foo:
        click.echo(f"Hello {foo}!")
    if count:
        click.echo(f"Hello {count}!")
    if name:
        click.echo(f"Hello {name}!")

if __name__ == '__main__':
    hello()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

双手揣兜 2025-01-19 05:05:53

您的 try1 代码可以工作,但用户必须输入 --foo 开关。

尝试1

import click

@click.command()
@click.option('--foo', flag_value='foo', required=True, help='foo is bar.')
@click.option('--count', flag_value='count', required=True, help='Number of greetings.')
@click.option('--name', flag_value='name', required=True, help='The person to greet.')
def hello(foo, count, name):
    if not (count or name or foo):
        raise click.UsageError( 'Must specify --foo or bar or car')
    if foo:
        click.echo(f"Hello {foo}!")
    if count:
        click.echo(f"Hello {count}!")
    if name:
        click.echo(f"Hello {name}!")

if __name__ == '__main__':
    hello()

但你想要

我有一个用例,其中这 3 个参数之一必须是
必填字段。

使用 此答案,作者: @Stephen Rauch 提供互斥体来实现依赖选项,我认为这是你的答案。

这是代码

import click


class Mutex(click.Option):
    def __init__(self, *args, **kwargs):
        self.not_required_if: list = kwargs.pop("not_required_if")

        assert self.not_required_if, "'not_required_if' parameter required"
        kwargs["help"] = (kwargs.get("help", "") + "Option is mutually exclusive with " +
                          ", ".join(self.not_required_if) + ".").strip()
        super(Mutex, self).__init__(*args, **kwargs)

    def handle_parse_result(self, ctx, opts, args):
        current_opt: bool = self.name in opts
        for mutex_opt in self.not_required_if:
            if mutex_opt in opts:
                if current_opt:
                    raise click.UsageError(
                        "Illegal usage: '" + str(self.name) + "' is mutually exclusive with " + str(mutex_opt) + ".")
                else:
                    self.prompt = None
        return super(Mutex, self).handle_parse_result(ctx, opts, args)


@click.command()
@click.option('--foo', flag_value='foo', cls=Mutex, not_required_if=["count", "name"], help='foo is bar.')
@click.option('--count', flag_value='count',  hide_input=True, cls=Mutex, not_required_if=["foo", "name"], help='Number of greetings.')
@click.option('--name', flag_value='name',  hide_input=True, cls=Mutex, not_required_if=["count", "foo"], help='The person to greet.')
def login(ctx=None, foo: bool = False, count: bool = False, name: bool = False) -> None:
    print("...do what you like with the params you got...")

    if foo:
        click.echo(f"Hello {foo}!")
    if count:
        click.echo(f"Hello {count}!")
    if name:
        click.echo(f"Hello {name}!")
    
if __name__ == '__main__':
    login()

运行

$ python3 cc.py --name
Hello name!

$ python3 cc.py --foo
Hello name!

$ python3 cc.py --name --foo
Error: Illegal usage: 'name' is mutually exclusive with foo.

相关链接

python Click 中互斥的选项组

Your try1 code works but user must enter the --foo switch.

Try1

import click

@click.command()
@click.option('--foo', flag_value='foo', required=True, help='foo is bar.')
@click.option('--count', flag_value='count', required=True, help='Number of greetings.')
@click.option('--name', flag_value='name', required=True, help='The person to greet.')
def hello(foo, count, name):
    if not (count or name or foo):
        raise click.UsageError( 'Must specify --foo or bar or car')
    if foo:
        click.echo(f"Hello {foo}!")
    if count:
        click.echo(f"Hello {count}!")
    if name:
        click.echo(f"Hello {name}!")

if __name__ == '__main__':
    hello()

But you want

I have a use case where one out of these 3 parameters has to be a
required field.

Using this answer by @Stephen Rauch that provide mutex to implement dependence option I think its your answer.

Here is the Code

import click


class Mutex(click.Option):
    def __init__(self, *args, **kwargs):
        self.not_required_if: list = kwargs.pop("not_required_if")

        assert self.not_required_if, "'not_required_if' parameter required"
        kwargs["help"] = (kwargs.get("help", "") + "Option is mutually exclusive with " +
                          ", ".join(self.not_required_if) + ".").strip()
        super(Mutex, self).__init__(*args, **kwargs)

    def handle_parse_result(self, ctx, opts, args):
        current_opt: bool = self.name in opts
        for mutex_opt in self.not_required_if:
            if mutex_opt in opts:
                if current_opt:
                    raise click.UsageError(
                        "Illegal usage: '" + str(self.name) + "' is mutually exclusive with " + str(mutex_opt) + ".")
                else:
                    self.prompt = None
        return super(Mutex, self).handle_parse_result(ctx, opts, args)


@click.command()
@click.option('--foo', flag_value='foo', cls=Mutex, not_required_if=["count", "name"], help='foo is bar.')
@click.option('--count', flag_value='count',  hide_input=True, cls=Mutex, not_required_if=["foo", "name"], help='Number of greetings.')
@click.option('--name', flag_value='name',  hide_input=True, cls=Mutex, not_required_if=["count", "foo"], help='The person to greet.')
def login(ctx=None, foo: bool = False, count: bool = False, name: bool = False) -> None:
    print("...do what you like with the params you got...")

    if foo:
        click.echo(f"Hello {foo}!")
    if count:
        click.echo(f"Hello {count}!")
    if name:
        click.echo(f"Hello {name}!")
    
if __name__ == '__main__':
    login()

Run

$ python3 cc.py --name
Hello name!

$ python3 cc.py --foo
Hello name!

$ python3 cc.py --name --foo
Error: Illegal usage: 'name' is mutually exclusive with foo.

Related link

Mutually exclusive option groups in python Click

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文