python argparse, поиск определенного файла, если параметр опущен

У меня есть аргумент для входного файла, и его легко обработать с помощью argparse

parser.add_argument( '-al', nargs = 1, type = argparse.FileType( 'r' ),
                     dest = 'alphabet' )

Этот параметр является необязательным, но если он опущен, мне все равно нужно получить этот входной файл, выполнив поиск в текущем каталоге. И если есть более одного или ни одного файла с расширением .al, я подниму ошибку, иначе откройте файл, который я нашел.

#if no alphabet look for .al file in current directory
if( args.alphabet == None ):
    AlFiles = [ f for f in os.listdir( '.' ) 
                if os.path.isfile( f ) and f.endswith( '.al' ) ]

    #there should be one file with .al extension
    if( len( AlFiles ) != 1 ):
            sys.exit( 'error: no alphabet file provided and '
                    'there are more than one or no .al file in current directory, '
                    'which leads to ambiguity' )

    args.alphabet = open( AlFiles[0], 'r' )

Есть ли способ выполнить это с помощью argparse, возможно, с параметрами по умолчанию или действиями. Если я выполняю поиск до разбора аргументов и возникает исключительная ситуация, я все равно не могу ее вызвать, потому что нужный файл может быть предоставлен аргументами командной строки. Я думал выполнить действие, если парсер не встретил нужный параметр, но не могу найти, как это сделать с помощью argparse.


person Yaroslav Kishchenko    schedule 16.08.2013    source источник


Ответы (1)


Вы можете исправить это, установив атрибут по умолчанию для аргумента.

parser = argparse.ArgumentParser()
parser.add_argument('-al',
                    type = argparse.FileType('r'),
                    default = [ f for f in os.listdir( '.' )
                                if os.path.isfile( f ) and f.endswith( '.al' )],
                    dest = 'alphabet' )

И после этого проведите проверку. Таким образом, у вас есть только одна функция, проверяющая наличие более одного или ни одного файла *.al, независимо от того, был ли аргумент опущен или нет.

Например, это может быть выполнено примерно так:

args =  parser.parse_args()
if isinstance(args.alphabet,types.ListType):
    if len(args.alphabet) != 1:
        parser.error("There must be exactly one alphabet in the directory")
    else:
        args.alphabet = open(args.alphabet[0])

Таким образом, args.alphabet будет содержать открытый файл, если был указан файл алфавита или в текущем рабочем каталоге есть только один файл алфавита, но вызовет ошибку, если в cwd их больше или нет.

Примечание. Поскольку мы получаем список, если аргумент -al опущен, argparse.FileType('r') не откроет ни одного файла. Вы также должны опустить nargs=1, так как это создаст список, содержащий один открытый файл, указанный пользователем в аргументе -al. Опускание этого атрибута даст нам необработанный открытый файл, указанный пользователем.

EDIT: вам нужно будет import types.

person angryfruitsalad    schedule 16.08.2013
comment
Итак, после синтаксического анализа я просто проверяю размер args.alphabet? А если файлов несколько, то все они будут открыты? - person Yaroslav Kishchenko; 16.08.2013
comment
Насколько я понимаю ваш вопрос, вы хотите открыть файл только в том случае, если это единственный файл * .al в каталоге. Проверьте мое редактирование для попытки решения. - person angryfruitsalad; 16.08.2013
comment
yah я получил ваш ответ, просто в add_arguments тип FileType, что означает, что все файлы открыты автоматически По крайней мере, вы не должны повторно открывать его снова args.alphabet = open(args.alphabet[0]) А если несколько файлов открыты, они будут закрыты, если мы поднимем ошибку? - person Yaroslav Kishchenko; 16.08.2013
comment
Вы правы, я пропустил это. Что именно вы хотите проанализировать с помощью аргумента -al? Имя файла .al или каталога, в котором он находится? - person angryfruitsalad; 16.08.2013
comment
Я просто хочу открыть один файл вот и все - person Yaroslav Kishchenko; 16.08.2013
comment
Я это понимаю. Возникает вопрос: что указывает пользователь с помощью аргумента -al? Если аргумент не опущен, вы указываете папку, содержащую файлы *.al, или указываете путь к файлу, например: path/to/file.al ? - person angryfruitsalad; 16.08.2013
comment
Нет, пользователь просто передает имя или путь к файлу. и если он опущен, я ищу текущий каталог (а не какой-либо другой) для этого файла с уже установленным расширением. - person Yaroslav Kishchenko; 16.08.2013
comment
Я надеюсь, что смог помочь вам, и моя попытка решить вашу проблему. Я был бы очень признателен, если бы вы приняли мой ответ, если он сработает для вас. Спасибо ;) - person angryfruitsalad; 16.08.2013