web-dev-qa-db-ja.com

python argparseで引数をオプションにする方法

私はmyprogのこれらの呼び出しを機能させ、他のものは機能させません。

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

特に、入力ファイルを指定して、出力ファイルを指定しないことを違法にしたいと思います。

3番目のケースでは、outfileのデフォルト名は「out.json」と見なされます。 2番目、3番目、4番目のケースでは、入力ファイルのデフォルト名は「file.n.json」と見なされます。ここで、nは整数のバージョン番号です。 4番目のケースでは、出力ファイルは「file.n + 1.json」になります。n+ 1は、入力ファイルのバージョン番号より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"がなくても、あたかも存在するかのように動作したことを示唆しています。

27
user1416227

出力ファイルのデフォルト引数を指定しました。

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で追加のロジックなしでこれを行う方法はわかりません。

13
BenDundee

選択した回答のアドオンとして:

ファイルを指定せずに-oを実行するオプションは、constnargs='?'と組み合わせて使用​​して実行できます。

ドキュメントから:

オプション文字列(-fや--fooなど)とnargs = '?'を指定してadd_argument()が呼び出された場合。これにより、オプションの引数が作成され、その後にゼロまたは1つのコマンドライン引数を続けることができます。コマンドラインを解析するときに、オプション文字列に続いてコマンドライン引数がない場合、代わりにconstの値が想定されます。例については、nargsの説明を参照してください。

16
mhristache