web-dev-qa-db-ja.com

argparseのコマンドライン引数としてのファイル-引数が無効な場合のエラーメッセージ

私は現在、このようなargparseを使用しています:

_import argparse
from argparse import ArgumentParser

parser = ArgumentParser(description="ikjMatrix multiplication")
parser.add_argument("-i", dest="filename", required=True,
    help="input file with two matrices", metavar="FILE")
args = parser.parse_args()

A, B = read(args.filename)
C = ikjMatrixProduct(A, B)
printMatrix(C)
_

ここで、_-i_の引数は読み取り可能なファイルであることに注意してください。どうやってやるの?

_type=open_、type=argparse.FileType('r')を追加しようとしましたが、機能しましたが、ファイルが有効でない場合、エラーメッセージが表示されます。どうやってやるの?

49
Martin Thoma

実際には非常に簡単です。ファイルが有効かどうかをチェックし、そうでない場合はエラーを書き込む関数を作成するだけです。その関数をtypeオプションと共に使用します。 argparse.Actionをサブクラス化することで、より洗練されたカスタムアクションを作成できますが、ここでは必要ないと思います。私の例では、開いているファイルハンドルを返します(以下を参照)。

#!/usr/bin/env python

from argparse import ArgumentParser
import os.path


def is_valid_file(parser, arg):
    if not os.path.exists(arg):
        parser.error("The file %s does not exist!" % arg)
    else:
        return open(arg, 'r')  # return an open file handle


parser = ArgumentParser(description="ikjMatrix multiplication")
parser.add_argument("-i", dest="filename", required=True,
                    help="input file with two matrices", metavar="FILE",
                    type=lambda x: is_valid_file(parser, x))
args = parser.parse_args()

A, B = read(args.filename)
C = ikjMatrixProduct(A, B)
printMatrix(C)
76
mgilson

Python 3.4でこれを行う方法は、 argparse.FileType クラスを使用することです。終了時に入力ストリーム。STDIN/STDOUTに擬似引数'-'を使用できるため、これも便利です。

FileTypeオブジェクトは擬似引数'-'を理解し、これをsys.stdinに自動的に変換して読み取り可能な FileType オブジェクトとsys.stdout書き込み可能 FileType オブジェクト

例:

#!/usr/bin/env python3

import argparse

if __== '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--infile', type=argparse.FileType('r', encoding='UTF-8'), 
                      required=True)
  args = parser.parse_args()
  print(args)
  args.infile.close()

そして、走ったとき...

  • 引数なし:

    $ ./stack_overflow.py
    usage: stack_overflow.py [-h] --infile INFILE
    stack_overflow.py: error: the following arguments are required: --infile
    
  • 存在しないファイルの場合:

    $ ./stack_overflow.py --infile notme
    usage: stack_overflow.py [-h] --infile INFILE
    stack_overflow.py: error: argument --infile: can't open 'notme': [Errno 2] No such file or directory: 'notme'
    
  • 既存のファイルの場合:

    $ ./stack_overflow.py --infile ./stack_overflow.py
    Namespace(infile=<_io.TextIOWrapper name='./stack_overflow.py' mode='r' encoding='UTF-8'>)
    
  • STDINに'-'を使用:

    $ echo 'hello' | ./stack_overflow.py --infile -
    Namespace(infile=<_io.TextIOWrapper name='<stdin>' mode='r' encoding='UTF-8'>)
    
28
mkobit

私はこれを見つけました:

def extant_file(x):
    """
    'Type' for argparse - checks that file exists but does not open.
    """
    if not os.path.exists(x):
        # Argparse uses the ArgumentTypeError to give a rejection message like:
        # error: argument input: x does not exist
        raise argparse.ArgumentTypeError("{0} does not exist".format(x))
    return x

if __== "__main__":
    import argparse, sys, os
    from argparse import ArgumentParser

    parser = ArgumentParser(description="ikjMatrix multiplication")
    parser.add_argument("-i", "--input",
        dest="filename", required=True, type=extant_file,
        help="input file with two matrices", metavar="FILE")
    args = parser.parse_args()

    A, B = read(args.filename)
    C = ikjMatrixProduct(A, B)
    printMatrix(C, args.output)

ソース: fhcrc.github.com

17
Martin Thoma