Нет ничего плохого в том, что argparse
принимает строку, и вы выполняете свою собственную проверку после. Иногда вы хотите проверить правильность имени файла, но не открывать его до конца (например, с помощью with open(filename) as f:
). Вероятно, это самый простой способ.
Альтернатива kalhartt's
Choices
класса будет использовать os.path
или glob
, чтобы получить список допустимых файлов.
p.add_argument('file',choices=glob.glob('*.txt'))
In [91]: p.parse_args('test.txt'.split())
Out[91]: Namespace(file='test.txt')
Проблема с этим состоит в том, что помощь и сообщения об ошибках могут быть чрезмерно длинным списком всех допустимых имен файлов.
Этот choices
не работает вместе с FileType
. Это потому, что он проверяет на выбор после того, как файл был открыт
p.add_argument('file',choices=[open('test.txt')],type=argparse.FileType('r'))
p.parse_args('test.txt'.split())
# usage: python [-h] {<open file 'test.txt', mode 'r' at 0xa102f98>}
# error: argument file: invalid choice: <open file 'test.txt', mode 'r' at 0xa102f40>
# (choose from <open file 'test.txt', mode 'r' at 0xa102f98>)
Даже если имена файлов совпадают, идентификаторы двух открытых файлов не совпадают. Как показано в примере kalhartt's
, объект choices
должен иметь функцию __contains__
(которая проверяет имя файла, например f.name.endswith('txt')
).
Но если вам действительно нравится то, что FileType
открывает файл, я могу представить его подклассификацию, поэтому он проверяет наличие расширений.
class FileTypeWithExtension(argparse.FileType):
def __init__(self, mode='r', bufsize=-1, extension=None):
self._extension = extension
super(FileTypeWithExtension, self).__init__()
def __call__(self, string):
if string != '-' and self._extension:
if not string.endswith(self._extension):
# just testing against one extension for now
raise argparse.ArgumentTypeError('wrong extension')
return super(FileTypeWithExtension, self).__call__(string)
p.add_argument('file',type=FileTypeWithExtension('r',extension='txt'))
p.parse_args('test.tst'.split())
#usage: ipython [-h] file
#ipython: error: argument file: wrong extension
p.parse_args('test.txt'.split())
# Namespace(file=<open file 'test.txt', mode 'r' at 0xa13ce90>)
'argparse' предоставляет вам некоторые инструменты для проверки аргументов, но не требует, чтобы вы их использовали. 'FileType' - это удобная функция, предназначенная для использования в обычных скриптовых приложениях. Вам не нужно использовать его, если он не подходит для вашего приложения. То же самое касается «выборов». – hpaulj