使用所需的子解析器进行 Argparse

我使用的是 Python 3.4,我试图在子解析器中使用 argparse,我想要有一个类似于 Python 2.x 中的行为,如果我不提供位置参数(指示子解析器/子程序) ,我将得到一个有用的错误消息。例如,使用 python2,我将得到以下错误消息:

$ python2 subparser_test.py
usage: subparser_test.py [-h] {foo} ...
subparser_test.py: error: too few arguments

我正在按照 https://stackoverflow.com/a/22994500/3061818中的建议设置 required属性,但是在 Python 3.4.0中出现了一个错误: TypeError: sequence item 0: expected str instance, NoneType found-完整回溯:

$ python3 subparser_test.py
Traceback (most recent call last):
File "subparser_test.py", line 17, in <module>
args = parser.parse_args()
File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1717, in parse_args
args, argv = self.parse_known_args(args, namespace)
File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1749, in parse_known_args
namespace, args = self._parse_known_args(args, namespace)
File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/argparse.py", line 1984, in _parse_known_args
', '.join(required_actions))
TypeError: sequence item 0: expected str instance, NoneType found

这是我的节目 subparser_test.py-改编自 https://docs.python.org/3.2/library/argparse.html#sub-commands:

import argparse


# sub-command functions
def foo(args):
print('"foo()" called')


# create the top-level parser
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
subparsers.required = True


# create the parser for the "foo" command
parser_foo = subparsers.add_parser('foo')
parser_foo.set_defaults(func=foo)


args = parser.parse_args()
args.func(args)

相关问题: 为什么这段 argparse 代码在 Python2和 Python3之间的行为有所不同?

32444 次浏览

You need to give subparsers a dest.

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='cmd')
subparsers.required = True

Now:

1909:~/mypy$ argdev/python3 stack23349349.py
usage: stack23349349.py [-h] {foo} ...
stack23349349.py: error: the following arguments are required: cmd

In order to issue this 'missing arguments' error message, the code needs to give that argument a name. For a positional argument (like subparses), that name is (by default) the 'dest'. There's a (minor) note about this in the SO answer you linked.

One of the few 'patches' to argparse in the last Python release changed how it tests for 'required' arguments. Unfortunately it introduced this bug regarding subparsers. This needs to be fixed in the next release (if not sooner).

update

If you want this optional subparsers behavior in Py2, it looks like the best option is to use a two stage parser as described in

How to Set a Default Subparser using Argparse Module with Python 2.7

There has been some recent activity in the related bug/issue

https://bugs.python.org/issue9253

update

A fix to this is in the works: https://github.com/python/cpython/pull/3027