目前,当我尝试在argparse中运行我的一个选项时,我必须先写一些东西,例如:
python3 main.py https://example.com ping-history
这对我的其他选项(ping和其他选项)很好,因为我需要指定我想要访问的网站。但是我需要它来为我的一个选项做一个例外。 所以它看起来像这样:
python3 main.py ping-history
我尝试添加:
nargs="?"
为:
parser.add_argument('filename', help="input file")
这解决了这个问题,但是当我尝试运行--verbose或--silent:
时python3 main.py https://example.com -v title
我明白了:
main.py: error: argument commands: invalid choice: 'https://example.com'
我不确定发生了什么,有人可以解释一下吗?
编辑:解析器文件:
import argparse
VERSION = "v1.0.0 (2017-06-16)"
def add_options(parser):
"""add options"""
group = parser.add_mutually_exclusive_group()
group.add_argument("-s", "--silent", dest="silent", help="Less output", action="store_true")
group.add_argument("-v", "--verbose", dest="verbose", help="More output", action="store_true")
parser.add_argument("-V", "--version", action="version", version=VERSION)
parser.add_argument('filename', help="input file", nargs="?")
def add_commands(parser):
"""Adds commands"""
subparser = parser.add_subparsers(title="commands (positional arguments)", help="Available commands",\
dest="commands")
subparser.add_parser("lines", help="count lines in textfile")
subparser.add_parser("words", help="count words in textfile")
subparser.add_parser("letters", help="count letters in textfile")
subparser.add_parser("all", help="count all")
subparser.add_parser("word_frequency", help="count word frequency")
subparser.add_parser("letter_frequency", help="count letter frequency")
#subparser.add_parser("filename", help= "filename to analyze")
subparser.add_parser("ping", help="ping a website")
subparser.add_parser("ping-history", help="show past status code")
subparser.add_parser("quote", help="retrieve todays quote")
subparser.add_parser("title", help="retrive titel from page")
def parse_options():
"""add options"""
parser = argparse.ArgumentParser()
add_options(parser)
add_commands(parser)
arg, unknown_args = parser.parse_known_args()
options = {}
options["known_args"] = vars(arg)
options["unknown_args"] = unknown_args
return options
答案 0 :(得分:1)
在我的评论中,我猜到你有一个可选的位置。但进一步认为你的错误更符合初始的可选位置。
In [42]: parser=argparse.ArgumentParser()
In [43]: a1 = parser.add_argument('name');
In [44]: parser.add_argument('-v',action='store_true');
In [45]: parser.add_argument('cmds',choices=['one','two'])
In [46]: parser.parse_args('foo one'.split())
Out[46]: Namespace(cmds='one', name='foo', v=False)
In [47]: parser.parse_args('foo -v one'.split())
Out[47]: Namespace(cmds='one', name='foo', v=True)
将第一个参数更改为可选:
In [48]: a1.nargs
In [49]: a1.nargs='?'
In [50]: parser.parse_args('foo one'.split())
Out[50]: Namespace(cmds='one', name='foo', v=False)
In [51]: parser.parse_args('foo -v one'.split())
usage: ipython3 [-h] [-v] [name] {one,two}
ipython3: error: argument cmds: invalid choice: 'foo' (choose from 'one', 'two')
...
如果我只给它一个字符串,我会得到同样的错误:
In [54]: parser.parse_args('foo'.split())
usage: ipython3 [-h] [-v] [name] {one,two}
ipython3: error: argument cmds: invalid choice: 'foo'
parse_args
在评估位置和选项之间交替。在做位置时,它会尝试处理尽可能多的字符串(使用regex
样式模式匹配)。一个 '?' position可以匹配一个空字符串。因此,当它只看到一个字符串'foo'时,它会将[]
与'name'匹配,并尝试将'foo'与'cmd'匹配。
有关于使解析看起来更进一步的错误/问题,并预期第二个位置可能会满足标志后的字符串。但是现在,当一个或多个位置是“可选的”时,不要混合使用标志和位置。
In [55]: parser.parse_args('foo one -v'.split())
Out[55]: Namespace(cmds='one', name='foo', v=True)
In [56]: parser.parse_args('-v foo one'.split())
Out[56]: Namespace(cmds='one', name='foo', v=True)
在完整的解析器中,第二个positional
是subparser。如上所述,它会尝试将['https://example.com']
应用于'?'论证和subparser。
所以工作电话是:
python3 main.py -v https://example.com title
如果只有部分commands
需要filename
,请考虑将该参数分配给这些子分析器,而不是将其作为父分析器的可选参数。
一般来说,使用subparser时父母的位置很棘手。标记所有父参数会更容易。