Я хотел бы иметь возможность вводить аргументы командной строки в файл, а затем передавать их в программу python с помощью argparse, используя опцию а не префиксный символ, например: $ python myprogram.py 1 2 --foo 1 -A somefile.txt --bar 2
Это почти то же самое, что и this question, за исключением того, что мне нужно иметь некоторые позиционные аргументы в начале; когда это решение вызывает parse_args
, оно терпит неудачу, если файл не имеет в нем позиционных аргументов.Как получить argparse для чтения аргументов из файла с опцией после позиционных аргументов
ответ
Если somefile.txt
содержит
one
two
three
затем
$ python myprogram.py 1 2 --foo 1 @somefile.txt --bar 2
с помощью prefix char
эффективно такой же, как
$ python myprogram.py 1 2 --foo 1 one two three --bar 2
Другими словами, в самом начале синтаксического анализа, то @ файл считывается, и его содержимое сплайсируется в argv
. Оттуда разбор происходит нормально.
Одна вещь, которую я предложил в другом вопросе SO, заключалась в том, чтобы реализовать это сращивание себя перед анализом.
Ответ, на который вы ссылаетесь, использует действие custom
; в том месте, где обычно Action
просто помещает value
в namespace
, это действие считывает и анализирует файл:
parser.parse_args(f.read().split(), namespace)
Вариант разбирает в новые namespace
и выборочно копия значений к основным namespace
.
Очевидно, ваша проблема заключается в том, что ваш парсер имеет некоторые необходимые аргументы, и этот parse_args
вызывает ошибку, если файл не содержит этих. Это неудивительно.
Одним из решений является использование другого файла parser
для этого файла, который предназначен для работы только с содержимым файла. Я бы просто определил его глобально.
alt_parser.parse_args(f.read().split(), namespace)
Другими словами, вы не должны использовать parser
, который был передан в качестве параметра.
Вариация на это поместить имя файла в пространстве имен, и справиться с ней после первого разбора:
args = parser.parse_args()
if args.A:
argv = open(args.A).read().split()
args1 = alt_parser.parse_args(argv)
Но вы можете спросить, мы не можем сказать, какие аргументы уже проанализированы, и учитывайте это при обработке -A
? parser
не является государственной машиной; разбор не изменяет ни одного из его атрибутов. Единственной переменной, которая отражает синтаксический анализ до сих пор, является namespace
. Все остальные переменные синтаксического анализа являются локальными для вызывающего кода.
Должно было сказать: '@' делает все правильно, но я копирую поведение другой программы. Это имеет смысл; теперь трюк делает второй парсер с теми же аргументами, за исключением без обязательных позиционных. – petrelharp
Сначала вы можете сделать этот синтаксический анализатор и использовать его как «родителей» для основного. Тогда вам просто нужно добавить 'positionals' в' child'. – hpaulj