dest
с '-' обрабатывается по-разному с необязательным и позиционным.
In [298]: import argparse
In [299]: parser = argparse.ArgumentParser()
In [300]: a1 = parser.add_argument('--a-string');
In [301]: a2 = parser.add_argument('foo-string');
In [302]: parser.print_help()
usage: ipython3 [-h] [--a-string A_STRING] foo-string
positional arguments:
foo-string
optional arguments:
-h, --help show this help message and exit
--a-string A_STRING
dest
для optional
получается из первого 'длинного' флага, заменяя любой внутренний '-' с '_'. dest
для позиционного значения является первым аргументом без каких-либо замен. У вас есть полный контроль над позиционным dest
.
In [304]: args = parser.parse_args(['xxx'])
In [305]: args
Out[305]: Namespace(a_string=None, **{'foo-string': 'xxx'})
In [306]: args.a_string
Доступ к da sh dest все еще возможен:
In [307]: vars(args)['foo-string']
Out[307]: 'xxx'
In [308]: getattr(args, 'foo-string')
Out[308]: 'xxx'
Замена '- / _' выполнена поэтому вы можете использовать '-' во флаге (обычная практика POSIX), но по-прежнему обращаться к атрибуту с синтаксисом точки.
Внутренне argparse
использует getattr
и setattr
, поэтому он не ограничить dest
. Это не обязательно должно быть действительное имя python. Это верно как для опциональных, так и для позиционных.
Если я дал необязательное значение dest
(отличное от флага),
In [310]: a1.dest = 'a-string' # changing the existing argument
In [312]: parser.print_help()
usage: ipython3 [-h] [--a-string A-STRING] foo-string
positional arguments:
foo-string
optional arguments:
-h, --help show this help message and exit
--a-string A-STRING
Это изменило 'A_STRING' на ' A-STRING ', но также изменили имя атрибута:
In [313]: args = parser.parse_args(['xxx'])
In [314]: args
Out[314]: Namespace(**{'a-string': None, 'foo-string': 'xxx'})
metavar
позволяет нам контролировать, как значение отображается в справке. Затем мы можем выбрать dest
как что-нибудь практичное (или непрактичное, если мы предпочитаем).
In [315]: a1.dest='a_string'; a1.metavar='MY-STRING'
In [316]: a2.dest='foo_bar'; a2.metavar='YOUR-STRING'
In [317]: parser.print_help()
usage: ipython3 [-h] [--a-string MY-STRING] YOUR-STRING
positional arguments:
YOUR-STRING
optional arguments:
-h, --help show this help message and exit
--a-string MY-STRING
In [318]: args = parser.parse_args(['xxx'])
In [319]: args
Out[319]: Namespace(a_string=None, foo_bar='xxx')
Уродливое назначение, независимо от флагов и метавара:
In [320]: a1.dest='a-#$'; a2.dest='-xxx$3'
In [321]: args = parser.parse_args(['xxx'])
In [322]: args
Out[322]: Namespace(**{'-xxx$3': 'xxx', 'a-#$': None})
In [323]: getattr(args, '-xxx$3')
Out[323]: 'xxx'
In [324]: parser.print_usage()
usage: ipython3 [-h] [--a-string MY-STRING] YOUR-STRING
Некоторые утверждали что позиционеры должны выполнять замену '- / _'. Но поскольку metavar
дает полный контроль над отображением справки, в этом нет необходимости. В лучшем случае, если бы вы просто заставили positionals
вести себя немного больше как `optionals.
Ваши возможности с metavar
более ограничены. Специальные символы могут испортить форматирование usage
, особенно если используется длинное (многострочное) или с взаимоисключающими группами. Это форматирование довольно хрупкое.