Как перемежающиеся / смешанные аргументы должны обрабатываться в argparse-module в версиях, предшествующих Python3.7? - PullRequest
2 голосов
/ 24 июня 2019

При соблюдении официальной документации для обновления с optparse до argparse следующий простой парсер

import optparse
def parse_with_optparser(args):
    opt_parser = optparse.OptionParser()
    opt_parser.add_option('-a', action="store_true")
    return opt_parser.parse_args(args)

становится:

def parse_with_argparser(args):
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('-a', action="store_true")
    arg_parser.add_argument("sources", nargs='*')
    return arg_parser.parse_args(args) 

т.е.. добавлен дополнительный позиционный аргумент sources.

Однако optparse поддерживает перемежающиеся (или смешанные в argparse -parlance) аргументы по умолчанию, то есть мы можем назвать успешными для

args = ['file1', '-a', 'file2']
parse_with_optparser(args) 
# ({'a': True}, ['file1', 'file2'])

, но argparse не поддерживает смешанные аргументы, и его использование приводит к ошибке:

parse_with_argparser(args) 
# error: unrecognized arguments: file2

Начиная с Python3.7, существует parse_intermixed_args (вместо parse_args), который обрабатывает перемеженные / смешанные аргументы так же, как optparse. Тем не менее, фреймворк нацелен на Python2.7 и Pyton> = 3.3, и поэтому использование parse_intermixed_args не обрезает его.

Как перемежающиеся / смешанные аргументы должны обрабатываться в argparse в версиях, предшествующих Python3.7?


Некоторые тестовые случаи:

      Input                         Output

['file1', 'file2', '-a']       Namespace(a=True, sources=['file1', 'file2'])
['-a', 'file1', 'file2']       Namespace(a=True, sources=['file1', 'file2'])
['file1', '-a', 'file2']       Namespace(a=True, sources=['file1', 'file2'])
['file1', '-a', '-b']          error (-b is unknown option)

1 Ответ

0 голосов
/ 01 июля 2019

Я следовал совету @ hpaulj и использовал parse_known_args, чтобы иметь возможность обрабатывать смешанные параметры вручную на этапе последующей обработки:

import argparse
def parse_with_argparser(args):
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('-a', action="store_true")
    # thus, "sources" is also a part of the help-message:
    arg_parser.add_argument("sources", nargs='*')

    # collecting unknown-options for post processing,
    # rather than exiting directly:
    result, unknown = arg_parser.parse_known_args(args)

    # post processing:
    for x in unknown:
        # filter out unknown options (like -b)
        # exit with error
        if x.startswith('-'):
            arg_parser.error("unknown argument "+x)
        # that must be one of the remaining sources:
        getattr(result, 'sources').append(x)
    return result 

Кажется, это проще,чем копирование и вставка кода для parse_intermixed_args, потому что модуль arparse не может обработать narg==SUPPRESS в Python <3.7, и это необходимо для патча. </p>

...