【问题标题】:How to indicate that at least one parameter is needed?如何表示至少需要一个参数?
【发布时间】:2015-07-05 01:43:51
【问题描述】:

我的脚本使用 ArgParse 接受 --full--last--check。如果未提供任何选项,则仅显示帮助消息。但在该消息中,参数显示为可选。

usage: script.py [-h] [--full] [--last] [--check log_file]

如果我使用关键字required,那么脚本将始终期望参数,这是不正确的。

usage: script.py [-h] --full --last --check log_file

那么,我怎样才能显示如下内容:

usage: script.py [-h] (--full |--last |--check log_file)

表示帮助是可选的,但至少有一个参数是必需的。

【问题讨论】:

  • 对于 Python 错误/问题补丁,我想知道对于这种“必需的任何”条件,什么是好的使用消息。 | 已用于互斥的 xor 条件。测试这样的条件更容易设计一个好的 API。

标签: python argparse


【解决方案1】:

关于自定义usage的问题:

解析器构造函数采用usage 参数。立竿见影的效果是设置一个属性:

parser = argparse.ArgumentParser( ... usage=custom_usage...)
print(parser.usage)
# should show None or the custom_usage string

作为一个普通的 Python 对象属性,您可以在创建解析器后更改它。

usage_str = parser.format_usage()

format_usage 方法要求解析器创建将在帮助(和错误消息)中显示的用法。如果parser.usage 的值为None,它会根据参数对其进行格式化。如果是字符串,则按原样使用(我认为它填充像%(prog)s 这样的值)。

因此您可以从头开始编写用法字符串。或者您可以设置解析器,获取当前使用字符串,然后根据您的需要对其进行编辑。编辑很可能是您在开发期间所做的事情,同时在 IDE 中测试解析器。但它可以即时完成。

一个粗略的例子:

In [441]: parser=argparse.ArgumentParser()
In [442]: g=parser.add_mutually_exclusive_group()
In [443]: g.add_argument('--foo')    
In [444]: g.add_argument('--bar')

In [445]: ustr = parser.format_usage()
# 'usage: ipython3 [-h] [--foo FOO | --bar BAR]\n'

In [450]: parser.usage = ustr.replace('[','(').replace(']',')')
In [451]: parser.format_usage()
# 'usage: usage: ipython3 (-h) (--foo FOO | --bar BAR)\n'

我已将 [] 替换为 ()(甚至在 -h 上:()。

目前测试args 属性的逻辑组合是最佳选择。在 parse_args 函数中,解析器维护一个它所看到的参数列表(实际上是一组)。这用于测试所需的参数和相互排斥的参数,但它在该代码之外不可用。

对于store_true(或错误)参数,只需检查它们的真值即可。对于其他人,我喜欢测试默认的None。如果您使用其他 default 值,请进行相应测试。 None 的一个好处是用户不能给你那个值。

也许测试参数最通用的方法是计算不是None的属性的数量:

In [461]: args=argparse.Namespace(one=None, tow=2, three=None)
In [462]: ll = ['one','tow','three']
In [463]: sum([getattr(args,l,None) is not None for l in ll])
Out[463]: 1

0 表示没有找到; >0至少有一份; ==len(ll) 全部找到; >1 违反互斥性; '==1' 表示必需的互斥。

【讨论】:

    【解决方案2】:

    正如@doublep 在他的回答中解释的那样,如果您想一次使用多个选项:

    手动将usage 消息更改为您想要的消息。

    Python argparse: Make at least one argument required添加以下代码:

    if not (args.full or args.last or args.check):
        parse.error('[-] Error: DISPLAY_ERROR_MESSAGE')
    

    【讨论】:

    • 我想编辑帮助中显示的使用信息,但似乎不可能,所以我要编写一条自定义信息,指示用户使用--帮助
    • old_usage=parser.format_usage() 给出格式化的使用行。您可以对其进行编辑,然后将其分配回 parser.usage = new_usage
    • @hpaulj 我昨天也发现了。在创建 ArgumentParser 对象时,一个可选参数是usage,这正是我要寻找的。来到这里将其作为答案发布,并且刚刚看到您的评论,所以如果您愿意,请回答问题,我会选择它。
    • @hpaulj 即使我很感激你的回答,因为我不明白你在说什么。这也是我在argparse 中学习新东西的更好机会。
    【解决方案3】:

    你可以使用add_mutually_exclusive_group():

    parser = argparse.ArgumentParser ()
    group  = parser.add_mutually_exclusive_group (required = True)
    group.add_argument ('--foo')
    group.add_argument ('--bar')
    

    但是,主要影响是您一次不能使用多个选项。

    【讨论】:

    • 我对 if-else 有同样的效果。我忘了提到我有兴趣允许 full 或 last 并同时检查
    猜你喜欢
    • 1970-01-01
    • 2011-10-07
    • 1970-01-01
    • 2017-11-16
    • 2017-02-08
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多