почему args.add_argument работает, если он указан в двух отдельных операторах, а не в одном в python?

Я пытаюсь использовать модуль argparse для анализа аргументов в командной строке. вот пример кода

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('bar')
parser.add_argument('-foo')
args=parser.parse_args()
print args

запустить это

python argparsing.py "hello"
Namespace(bar='hello', foo=None)

однако это не работает

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('bar','--foo')
#parser.add_argument('-foo')
args=parser.parse_args()
print args

запуск этого дает ошибку

python argparsing.py "hello"
Traceback (most recent call last):
  File "argparsing.py", line 3, in <module>
    parser.add_argument('bar','-foo')
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 1267, in add_argument
    kwargs = self._get_optional_kwargs(*args, **kwargs)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/argparse.py", line 1397, in _get_optional_kwargs
    raise ValueError(msg % tup)
ValueError: invalid option string 'bar': must start with a character '-'

Единственная разница между ними заключается в том, что я добавляю аргумент отдельно (в две строки) в первый код, но добавляю их в ту же строку, что и один оператор в ошибочном коде. может кто-нибудь помочь мне понять это лучше?


person eagertoLearn    schedule 01.10.2013    source источник


Ответы (3)


Вы не делаете то же самое. Посмотрите документы:

имя или флаги - либо имя, либо список строк параметров, например. foo или -f, --foo.

Вы не можете указать список позиционных аргументов, только один позиционный аргумент или список опций (флагов). Итак, когда вы пытаетесь дать ему 'bar', '--foo', он пытается проанализировать 'bar' как вариант, но не может, потому что он не начинается с -.

И, как объясняется в следующем разделе, когда вы даете это список опций, вы даете ему список альтернативных имен для одного и того же флага, а не кучу отдельных флагов. Итак, вы не хотите делать то, что пытаетесь сделать в первую очередь.

person abarnert    schedule 01.10.2013
comment
означает ли это, что parser.add_argument('-f', '--foo-bar', '--foo')', results in only flag in which f, foo-bar и foo` эквивалентны? - person eagertoLearn; 02.10.2013
comment
@ user2708477: Да. Но вы можете попробовать и убедиться в этом так же легко, как и спросить. Если вы parse_args(['-fspam', '--foo=eggs']) или запустите программу с python argparsing.py -fspam --foo=eggs, вы получите Namespace(foo_bar='eggs'). - person abarnert; 02.10.2013
comment
@ user2708477: Кроме того, если вы читаете документы, должно быть очевидно, что все указанные флаги будут иметь одни и те же action, dest и т. д. Как еще это могло бы работать? Кроме того… ваш пример посимвольно идентичен одному из примеров в документации в разделе dest, который уже показывает, что происходит. - person abarnert; 02.10.2013
comment
извините, я немного запутался. когда я запускаю это python argparsing.py -fspam -f=eggs, я получаю Namespace(foo_bar='eggs'). как мог, foo_bar = egg, когда я установил -f=eggs в командной строке - person eagertoLearn; 02.10.2013
comment
@ user2708477: Потому что -f, --foo-bar и --foo — это один и тот же вариант. Если вы не указали dest для этой опции: ArgumentParser генерирует значение dest, беря первую длинную строку опции и удаляя начальную строку --. Все это объяснено в документах, которые я связал для вас. И запись в документах намного лучше, чем запись в моих комментариях. - person abarnert; 02.10.2013

add_argument предназначен для добавления одного аргумента. 'bar' — один позиционный аргумент; '--foo' — один из необязательных аргументов. Вы не можете сделать аргумент, который является одновременно позиционным и необязательным, отсюда и ошибка.

Если вы хотите определить аргумент, но назвать опцию по-другому, используйте dest:

# accept an option --foo X, and store X into args.bar
parser.add_argument('--foo', dest='bar')

Обратите внимание, что вы можете определить несколько псевдонимов для одного необязательного аргумента, например.

parser.add_argument('-f', '--foo', '--frobnicate')
person nneonneo    schedule 01.10.2013
comment
в документах добавлено несколько необязательных аргументов, например parser.add_argument('-f', '--foo-bar', '--foo'). - person eagertoLearn; 02.10.2013
comment
@ user2708477: все это псевдонимы для необязательного аргумента. Вы пытались определить аргумент, который одновременно был позиционным и необязательным. - person nneonneo; 02.10.2013

Итак, вы даете argparse два совершенно разных способа определения аргумента. Так что он выдает ошибку, потому что не может понять ваш ввод

Один из способов определения аргумента — не использовать тире, как в первом случае.

parser.add_argument("bar")  # This is a required argument

Другой - использовать тире

parser.add_argument("-f", "--foo")  

--foo — это просто еще один способ указать тот же аргумент, что и -f. Это не обязательный аргумент, как аргументы без тире (bar), если только вы не хотите, чтобы он был обязательным аргументом.

person Greg    schedule 01.10.2013