Python argparse:至少需要一个参数

Ada*_*tan 81 python argparse

我已经使用argparse了Python程序,可以-process,-upload或两者:

parser = argparse.ArgumentParser(description='Log archiver arguments.')
parser.add_argument('-process', action='store_true')
parser.add_argument('-upload',  action='store_true')
args = parser.parse_args()
Run Code Online (Sandbox Code Playgroud)

没有至少一个参数,该程序毫无意义.如何配置argparse强制选择至少一个参数?

更新:

评论之后:使用至少一个选项参数化程序的Pythonic方法是什么?

phi*_*hag 94

if not (args.process or args.upload):
    parser.error('No action requested, add -process or -upload')
Run Code Online (Sandbox Code Playgroud)


bre*_*nce 27

args = vars(parser.parse_args())
if not any(args.values()):
    parser.error('No arguments provided.')
Run Code Online (Sandbox Code Playgroud)

  • +1为广义解决方案.也喜欢使用`vars()`,这对于将精心命名的选项传递给带有**的构造函数也很有用. (3认同)

Jac*_*zny 20

如果不是'或两者'部分(我最初错过了这个)你可以使用这样的东西:

parser = argparse.ArgumentParser(description='Log archiver arguments.')
parser.add_argument('--process', action='store_const', const='process', dest='mode')
parser.add_argument('--upload',  action='store_const', const='upload', dest='mode')
args = parser.parse_args()
if not args.mode:
    parser.error("One of --process or --upload must be given")
Run Code Online (Sandbox Code Playgroud)

尽管如此,使用子命令可能更好.

  • 我想他想要允许`--process`或`--upload`,而不是XOR.这可以防止同时设置两个选项. (4认同)

Knu*_*nut 14

我知道这很古老,但需要一个选项但禁止多个(XOR)的方式是这样的:

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-process', action='store_true')
group.add_argument('-upload',  action='store_true')
args = parser.parse_args()
print args
Run Code Online (Sandbox Code Playgroud)

输出:

>opt.py  
usage: multiplot.py [-h] (-process | -upload)  
multiplot.py: error: one of the arguments -process -upload is required  

>opt.py -upload  
Namespace(process=False, upload=True)  

>opt.py -process  
Namespace(process=True, upload=False)  

>opt.py -upload -process  
usage: multiplot.py [-h] (-process | -upload)  
multiplot.py: error: argument -process: not allowed with argument -upload  
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,OP 不需要 XOR。它是一个或两个,但不是没有,所以你的最后一个测试用例不符合他们的要求。 (4认同)
  • @kdopen:受访者确实澄清了这是原始问题的一种变体,我发现这很有用:“一种方法要求一个选择,但禁止一个以上的选择”也许Stack Exchange的礼节会要求一个新问题。但是这里有这个答案对我有帮助... (2认同)
  • 我会支持这个答案的用处,这最终正是我想要的。 (2认同)
  • 这篇文章没有回答最初的问题 (2认同)
  • 这如何回答“至少一个”的问题? (2认同)
  • 不幸的是,OP 不需要异或。 (2认同)

Jan*_*sky 8

要求审查

  • 使用argparse(我会忽略这个)
  • 允许调用一个或两个动作(至少需要一个).
  • 尝试通过Pythonic(我宁愿称之为"POSIX")

在命令行上生活时也有一些隐含的要求:

  • 以易于理解的方式向用户解释用法
  • 选项应是可选的
  • 允许指定标志和选项
  • 允许与其他参数(如文件名或名称)结合使用.

使用docopt(文件managelog.py)的示例解决方案:

"""Manage logfiles
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  Password

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>
"""
if __name__ == "__main__":
    from docopt import docopt
    args = docopt(__doc__)
    print args
Run Code Online (Sandbox Code Playgroud)

尝试运行它:

$ python managelog.py
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h
Run Code Online (Sandbox Code Playgroud)

显示帮助:

$ python managelog.py -h
Manage logfiles
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  P    managelog.py [options] upload -- <logfile>...

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>
Run Code Online (Sandbox Code Playgroud)

并使用它:

$ python managelog.py -V -U user -P secret upload -- alfa.log beta.log
{'--': True,
 '--pswd': 'secret',
 '--user': 'user',
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': False,
 'upload': True}
Run Code Online (Sandbox Code Playgroud)

简短的选择 short.py

甚至可以有更短的变体:

"""Manage logfiles
Usage:
    short.py [options] (process|upload)... -- <logfile>...
    short.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  Password

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>
"""
if __name__ == "__main__":
    from docopt import docopt
    args = docopt(__doc__)
    print args
Run Code Online (Sandbox Code Playgroud)

用法如下:

$ python short.py -V process upload  -- alfa.log beta.log
{'--': True,
 '--pswd': None,
 '--user': None,
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': 1,
 'upload': 1}
Run Code Online (Sandbox Code Playgroud)

请注意,"process"和"upload"键的布尔值不是计数器.

事实证明,我们无法阻止这些词的重复:

$ python short.py -V process process upload  -- alfa.log beta.log
{'--': True,
 '--pswd': None,
 '--user': None,
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': 2,
 'upload': 1}
Run Code Online (Sandbox Code Playgroud)

结论

设计良好的命令行界面有时可能具有挑战性.

基于命令行的程序有多个方面:

  • 良好的命令行设计
  • 选择/使用适当的解析器

argparse 提供了很多,但限制了可能的情况,并可能变得非常复杂.

随着docopt事情要短得多,同时保留可读性,并提供高度的灵活性.如果你管理从字典中获取解析的参数并手动(或通过其他库调用schema)进行一些转换(到整数,打开文件.. ),你可能会发现docopt很适合命令行解析.


hpa*_*ulj 7

对于http://bugs.python.org/issue11588,我正在探索将mutually_exclusive_group概念概括为处理此类案例的方法。

有了这个发展argparse.pyhttps://github.com/hpaulj/argparse_issues/blob/nested/argparse.py 我可以写:

parser = argparse.ArgumentParser(prog='PROG', 
    description='Log archiver arguments.')
group = parser.add_usage_group(kind='any', required=True,
    title='possible actions (at least one is required)')
group.add_argument('-p', '--process', action='store_true')
group.add_argument('-u', '--upload',  action='store_true')
args = parser.parse_args()
print(args)
Run Code Online (Sandbox Code Playgroud)

产生以下内容help

usage: PROG [-h] (-p | -u)

Log archiver arguments.

optional arguments:
  -h, --help     show this help message and exit

possible actions (at least one is required):
  -p, --process
  -u, --upload
Run Code Online (Sandbox Code Playgroud)

这接受诸如“-u”、“-up”、“--proc --up”等输入。

它最终运行类似于/sf/answers/470614651/的测试,但错误消息需要更清楚:

usage: PROG [-h] (-p | -u)
PROG: error: some of the arguments process upload is required
Run Code Online (Sandbox Code Playgroud)

我想知道:

  • 参数是否kind='any', required=True足够清晰(接受任何一组;至少需要一个)?

  • 用法(-p | -u)清楚吗?所需的mutual_exclusive_group 产生相同的结果。是否有一些替代符号?

  • 使用这样的组比phihag's简单的测试更直观吗?


fai*_*aig 6

最好的方法是使用python内置模块add_mutually_exclusive_group.

parser = argparse.ArgumentParser(description='Log archiver arguments.')
group = parser.add_mutually_exclusive_group()
group.add_argument('-process', action='store_true')
group.add_argument('-upload',  action='store_true')
args = parser.parse_args()
Run Code Online (Sandbox Code Playgroud)

如果您只想通过命令行选择一个参数,则只需使用required = True作为组的参数

group = parser.add_mutually_exclusive_group(required=True)
Run Code Online (Sandbox Code Playgroud)

  • 不幸的是,OP 不需要异或。OP 正在寻找 OR (4认同)
  • 这如何让你“至少一个”——它不是让你“恰好一个”吗? (2认同)

Nuc*_*eon 5

如果您需要一个 Python 程序至少使用一个参数运行,请添加一个没有选项前缀的参数(默认情况下为 - 或 --)并设置nargs=+(最少需要一个参数)。我发现这个方法的问题是,如果你不指定参数,argparse 会产生一个“参数太少”的错误并且不会打印出帮助菜单。如果您不需要该功能,以下是在代码中实现的方法:

import argparse

parser = argparse.ArgumentParser(description='Your program description')
parser.add_argument('command', nargs="+", help='describe what a command is')
args = parser.parse_args()
Run Code Online (Sandbox Code Playgroud)

认为当您添加带有选项前缀的参数时, nargs 控制整个参数解析器,而不仅仅是选项。(我的意思是,如果你有一个--option带有的标志nargs="+",那么--optionflag 需要至少一个参数。如果你有optionwith nargs="+",它需要至少一个整体参数。)


Bob*_*Bob 5

这达到了目的,这也将反映在 argparse 自动生成的--help输出中,恕我直言,这是大多数理智的程序员想要的(也适用于可选参数):

parser.add_argument(
    'commands',
    nargs='+',                      # require at least 1
    choices=['process', 'upload'],  # restrict the choice
    help='commands to execute'
)
Run Code Online (Sandbox Code Playgroud)

有关于此的官方文档: https ://docs.python.org/3/library/argparse.html#choices