Файл как аргумент командной строки для 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')
, и они работали, но если файл недействителен, я хотел бы получить сообщение об ошибке. Как я могу это сделать?
Ответы
Ответ 1
Это довольно легко. Вам просто нужно написать функцию, которая проверяет, действителен ли файл и записывает ошибку в противном случае. Используйте эту функцию с опцией 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)
Ответ 2
Я только что нашел это:
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 __name__ == "__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
Ответ 3
В Python 3.4 можно использовать класс argparse.FileType
. Обязательно закройте входной поток, когда закончите. Это также полезно, потому что вы можете использовать псевдо-аргумент '-'
для STDIN/STDOUT. Из документации:
Объекты FileType понимают псевдо-аргумент '-'
и автоматически преобразуют его в sys.stdin
для читаемых FileType
объектов и sys.stdout
для записываемых FileType
объекты
Пример:
#!/usr/bin/env python3
import argparse
if __name__ == '__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'>)