На Python 3.2 (и 2.7) вы получите эту ошибку, но не на 3.3 и 3.4 (без ответа).Поэтому в 3.3 / 3.4 вы можете проверить, чтобы parsed_args
был пустым Namespace
.
. Более общим решением является добавление метода set_default_subparser()
(взят из ruamel.std.argparse).) и вызовите этот метод непосредственно перед parse_args()
:
import argparse
import sys
def set_default_subparser(self, name, args=None, positional_args=0):
"""default subparser selection. Call after setup, just before parse_args()
name: is the name of the subparser to call by default
args: if set is the argument list handed to parse_args()
, tested with 2.7, 3.2, 3.3, 3.4
it works with 2.6 assuming argparse is installed
"""
subparser_found = False
for arg in sys.argv[1:]:
if arg in ['-h', '--help']: # global help if no subparser
break
else:
for x in self._subparsers._actions:
if not isinstance(x, argparse._SubParsersAction):
continue
for sp_name in x._name_parser_map.keys():
if sp_name in sys.argv[1:]:
subparser_found = True
if not subparser_found:
# insert default in last position before global positional
# arguments, this implies no global options are specified after
# first positional argument
if args is None:
sys.argv.insert(len(sys.argv) - positional_args, name)
else:
args.insert(len(args) - positional_args, name)
argparse.ArgumentParser.set_default_subparser = set_default_subparser
def do_hi():
print('inside hi')
a = argparse.ArgumentParser()
b = a.add_subparsers()
sp = b.add_parser('hi')
sp.set_defaults(func=do_hi)
a.set_default_subparser('hi')
parsed_args = a.parse_args()
if hasattr(parsed_args, 'func'):
parsed_args.func()
Это будет работать с 2.6 (если argparse
установлен из PyPI), 2.7, 3.2, 3.3, 3.4.И позволяет вам делать и
python3 default_subcommand.py
и
python3 default_subcommand.py hi
с одинаковым эффектом.
Позволяет выбрать новый подпарсер по умолчанию вместоодин из существующих.
Первая версия кода позволяет установить один из ранее определенных подпарсеров как один по умолчанию.Следующая модификация позволяет добавить новый подпараметр по умолчанию, который затем может быть использован для специальной обработки случая, когда субпарсер не был выбран пользователем (разные строки отмечены в коде)
def set_default_subparser(self, name, args=None, positional_args=0):
"""default subparser selection. Call after setup, just before parse_args()
name: is the name of the subparser to call by default
args: if set is the argument list handed to parse_args()
, tested with 2.7, 3.2, 3.3, 3.4
it works with 2.6 assuming argparse is installed
"""
subparser_found = False
existing_default = False # check if default parser previously defined
for arg in sys.argv[1:]:
if arg in ['-h', '--help']: # global help if no subparser
break
else:
for x in self._subparsers._actions:
if not isinstance(x, argparse._SubParsersAction):
continue
for sp_name in x._name_parser_map.keys():
if sp_name in sys.argv[1:]:
subparser_found = True
if sp_name == name: # check existance of default parser
existing_default = True
if not subparser_found:
# If the default subparser is not among the existing ones,
# create a new parser.
# As this is called just before 'parse_args', the default
# parser created here will not pollute the help output.
if not existing_default:
for x in self._subparsers._actions:
if not isinstance(x, argparse._SubParsersAction):
continue
x.add_parser(name)
break # this works OK, but should I check further?
# insert default in last position before global positional
# arguments, this implies no global options are specified after
# first positional argument
if args is None:
sys.argv.insert(len(sys.argv) - positional_args, name)
else:
args.insert(len(args) - positional_args, name)
argparse.ArgumentParser.set_default_subparser = set_default_subparser
a = argparse.ArgumentParser()
b = a.add_subparsers(dest ='cmd')
sp = b.add_parser('hi')
sp2 = b.add_parser('hai')
a.set_default_subparser('hey')
parsed_args = a.parse_args()
print(parsed_args)
Опция «по умолчанию» будетвсе еще не отображается в справке:
python test_parser.py -h
usage: test_parser.py [-h] {hi,hai} ...
positional arguments:
{hi,hai}
optional arguments:
-h, --help show this help message and exit
Однако теперь можно различать и обрабатывать отдельно вызов одного из предоставленных подпарсеров и вызов подпаратера по умолчанию, когда аргумент не был предоставлен:
$ python test_parser.py hi
Namespace(cmd='hi')
$ python test_parser.py
Namespace(cmd='hey')