当一个选项放在其余位置参数的前面时,为什么argparse会失败?

2024-06-08 18:30:01 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑一下scratch.py中使用python 3.7.2的测试argparse示例:

import sys
import argparse
import yaml


def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--sound', nargs='?', default=None)
    parser.add_argument('greeting')
    parser.add_argument('name')
    parser.add_argument('params', nargs='*')
    return vars(parser.parse_args(sys.argv[1:]))


def main():
    print(yaml.dump((get_args())))


if __name__ == "__main__":
    main()

如果我使用它:

(websosadmin) ~/wk/cliosoft/websosadmin/sosadmin_cli $ python scratch.py hello john loud red
greeting: hello
name: john
params:
- loud
- red
sound: null

(websosadmin) ~/wk/cliosoft/websosadmin/sosadmin_cli $ python scratch.py --sound bell hello john loud red
greeting: hello
name: john
params:
- loud
- red
sound: bell

(websosadmin) ~/wk/cliosoft/websosadmin/sosadmin_cli $ python scratch.py hello --sound bell john loud red
greeting: hello
name: john
params:
- loud
- red
sound: bell

(websosadmin) ~/wk/cliosoft/websosadmin/sosadmin_cli $ python scratch.py hello john --sound bell loud red
usage: scratch.py [-h] [--sound [SOUND]] greeting name [params [params ...]]
scratch.py: error: unrecognized arguments: loud red

为什么第四个案子失败了


Tags: namepyaddparserhelloredparamsargument
2条回答

hello john  sound bell loud red

解析为:

greeting = 'hello'
name = 'john'
params = []
sound = 'bell'

['loud','red']是剩余的

解析器也可以处理位置和可选的。它使用正则表达式样式的模式匹配将位置集分配给下一个可选('sound')。'“greeting”和“name”都需要一个字符串params'可以接受任何列表('*'),包括空列表。一旦用光了,就没有更多的理由去消耗“loud”和“red”

这是一个棘手的行为,并不理想。在这个主题上至少有一个bug/问题,但是如果我的记忆是正确的,那就不是一件容易修补的事情

更改为nargs='+'应该给出正确的解析

这个答案建立在hpaulj的反应之上

这是argparse中的一个bug,但是有一个解决方法:用parse_intermixed_args替换parse_args

这在问题的例子中是有效的(在实际的应用程序中是复杂的,有许多子命令和不同的标志和位置参数),但是如果使用argparse.REMAINDER之类的东西,它可能会失败

相关问题 更多 >