как сделать аргумент необязательным в python argparse

Я хотел бы, чтобы эти заклинания myprog работали, и никаких других.

$ python3 myprog.py -i infile -o outfile
$ python3 myprog.py -o outfile
$ python3 myprog.py -o
$ python3 myprog.py 

в частности, я хочу сделать незаконным указание infile, но не outfile.

в третьем случае предполагается имя outfile по умолчанию: "out.формат JSON."Во втором, третьем и четвертом случаях предполагается имя входного файла по умолчанию," file.n.json", где n-целочисленный номер версии. В четвертом случае выходной файл будет файл".n+1.json", где n+1 - версия номер один больше, чем версия входного файла. Соответствующий раздел моего кода:

import argparse

parser = argparse.ArgumentParser(description="first python version")
parser.add_argument('-i', '--infile', nargs=1, type=argparse.FileType('r'), help='input file, in JSON format')
parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), default='out.json', help='output file, in JSON format')

args = parser.parse_args()

print("Here's what we saw on the command line: ")
print("args.infile",args.infile)
print("args.outfile",args.outfile)

if args.infile and not args.outfile:
    parser.error("dont specify an infile without specifying an outfile")
elif not args.infile:
    print("fetching infile")
else: # neither was specified on the command line
    print("fetching both infile and outfile")

проблема в том, когда я бегу

$ python3 myprog.py -i infile.json

вместо ошибки парсера, на которую я надеялся, я получаю:

Here's what we saw on the command line: 
args.infile [<_io.TextIOWrapper name='infile.json' mode='r' encoding='UTF-8'>]
args.outfile <_io.TextIOWrapper name='out.json' mode='w' encoding='UTF-8'>
fetching both infile and outfile

...это говорит о том, что, хотя в командной строке не было "-o", она действовала так, как будто была.

2 ответов


вы указали аргумент по умолчанию для outfile.

parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), default='out.json', help='output file, in JSON format')

если -o опция не указана в командной строке, парсер arg вставляет аргумент по умолчанию.

заменить на:

parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), help='output file, in JSON format')

и все должно работать, как вы ожидаете.


если вы хотите иметь возможность указать -o, без имени, вы, вероятно, хотите что-то вроде:

out_file = args.out if args.out is not None else 'json.out'

Я не уверен, что соответствующий параметр None или '' (т. е. пустая строка), если указать -o без параметра--я подозреваю, что это None, но я точно не знаю. Вы должны проверить это, чтобы быть уверенным.

Я не знаю, как это сделать без дополнительной логики с argparse.


в качестве дополнения к выбранному ответ:

возможность работать -o без указания файла, можно сделать с помощью const в сочетании с nargs='?'.

документы:

когда add_argument () вызывается со строками опций (например,- f или --foo) и nargs='?'. Это создает необязательный аргумент, который можно использовать по нулю или одному аргументу командной строки. При разборе командной строки, если строка параметра встречается с no аргумент командной строки после этого будет принято значение const. Увидеть описание nargs для примеров.