2-х позиционные nargs='?'
. Такой позиционный элемент всегда «виден», так как пустой список соответствует этому nargs
.
Первый раз через 'text.txt' совпадает с first
и помещается в пространство имен. Второй раз, когда нет соответствующей строки, поэтому используется значение по умолчанию - так же, как если бы вы не дали эту строку в первый раз.
Если изменить first
иметь по умолчанию nargs
, я получаю
error: the following arguments are required: first
из 2-го синтаксического анализа. Несмотря на то, что в пространстве имен есть значение, он по-прежнему пытается получить значение от argv
. (это по умолчанию, но не совсем).
По умолчанию для позиционеров с nargs='?'
(или *
) сложны. Они являются необязательными, но не совсем так, как optionals
. Позиционные действия по-прежнему вызываются, но с пустым списком значений.
Я не думаю, что функция parents
делает что-нибудь для вас. preparser
уже обрабатывает набор аргументов; нет необходимости обрабатывать их снова в parser
, тем более, что все соответствующие строки аргументов были удалены.
Другой вариант - оставить родителей, но использовать по умолчанию sys.argv[1:]
во втором парсере. (Но остерегайтесь побочных эффектов, как открытие файлов)
args = parser.parse_args(namespace=args)
Третий вариант разобрать аргументы самостоятельно и объединить их со словарем update
.
adict = vars(preparse_args)
adict.update(vars(parser_args))
# taking some care in who overrides who
Для получения более подробной информации смотрите в файле argparse.py
на ArgumentParser._get_values
, в частности not arg_strings
случаев.
Примечание относительно FileType
. Этот тип прекрасно работает для небольших скриптов, где вы будете использовать файлы сразу и выйти. Это не так хорошо в больших программах, где вы можете закрыть файл после использования (закройте stdout
???) или используйте файлы в контексте with
.
редактировать - примечание на parents
add_argument
создает Action
объект, и добавляет его в список парсера действий. parse_args
в основном соответствует входным строкам с этими действиями.
parents
просто копирует эти объекты Action (по ссылке) от родителя к дочернему. Для детского анализатора это похоже на то, что действия были созданы с add_argument
напрямую.
parents
наиболее полезен, когда вы импортируете парсер и не имеете прямого доступа к его определению. Если вы определяете как родительский, так и дочерний, то parents
просто сохранит вам текст ввода/вырезания-n-paste.
Этот и другие вопросы SO (в основном вызванные копией по ссылке) показывают, что разработчики не собирались использовать как родительский, так и дочерний сеансы для синтаксического анализа. Это можно сделать, но есть глюки, которые они не рассматривали.
===================
Я могу представить себе определение пользовательских Action
класса, который будет «вести себя» в такой ситуации. Например, можно проверить пространство имен для некоторого значения по умолчанию, прежде чем добавлять его собственное (возможно, значение по умолчанию).
Рассмотрим, например, если я изменил action
из first
в 'Append':
preparser.add_argument('first', action='append', nargs='?')
Результат является:
1840:~/mypy$ python3 stack37147683.py /tmp/test.txt -d -c
Namespace(do_something=True, first=['/tmp/test.txt'], outfile=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>)
Namespace(clear_screen=True, do_something=True, first=['/tmp/test.txt', None], outfile=<_io.TextIOWrapper name='<stdout>' mode='w' encoding='UTF-8'>)
С первого синтаксического анализатора, first=['/tmp/test.txt']
; от второго, first=['/tmp/test.txt', None]
.
Из-за append
элемент из первого сохраняется, а второй по умолчанию добавлен новый параметр.
Почему вы не можете просто разобрать все арг сразу?Зачем вам сначала нужны подготовители? –
просто разбор исходных параметров с помощью 'parser.parse_args()' будет работать, не так ли? –
rerunning 'parser.parse_args()' ничего не делает. – MaDhAt2r