argparse и пользовательские действия - путь к коду неочевиден - PullRequest
0 голосов
/ 06 декабря 2018

Я использую argparse для анализа текстовых команд вместо того, чтобы пытаться развернуть свой собственный анализатор, но путь к коду не очевиден.Примите во внимание следующее:

import argparse

##class ReadAction(argparse.Action):
##    def __init__(self, option_strings, dest, nargs=None, **kwargs):
##        if nargs is not None:
##            raise ValueError("nargs not allowed")
##        super(ReadAction, self).__init__(option_strings, dest, **kwargs)
##    def __call__(self, parser, namespace, values, option_strings=None):
##        print("Read a file")
##        setattr(namespace, self.dest, values)

class ExitAction(argparse.Action):
    def __init__(self, option_strings, dest, nargs=None, **kwargs):
        if nargs is not None:
            raise ValueError("nargs not allowed")
        super(ExitAction, self).__init__(option_strings, dest, **kwargs)
    def __call__(self, parser, namespace, values, option_strings=None):
        print("Exiting the program")
        setattr(namespace, self.dest, values)

def setup_parser(parser):
##    parser.add_argument('read', help='Reads in a file', action=ReadAction)
    parser.add_argument('exit', help='Exit command', action=ExitAction)

def run():
    parser = argparse.ArgumentParser()
    setup_parser(parser)
    while True:
        raw_input = input("Command >>>").split(' ')
        args = parser.parse_args(raw_input)
        print(args)
    print('Good bye')

if __name__ == '__main__':
    run()

Если я запустил его как есть, я получу ожидаемый результат:

Command >>>exit
Exiting the program
Namespace(exit='exit')

Но если я уберу комментарии и запустлю снова, я получу это неожиданноеПоведение:

Command >>>exit
Read a file
usage: prog.py [-h] read exit
prog.py: error: the following arguments are required: exit

Кто-нибудь понимает путь кода через это?Как будто метод __call__ не вызывается (иронично).

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Оба аргумента read и exit ожидают одну строку.

При анализе первой строки вызывается ReadAction.__call__, устанавливающее значение в пространстве имен args.Если вы укажете только одну строку, парсер выдаст ошибку, потому что аргумент exit не был предоставлен.Если бы вы предоставили две строки, вторая строка была бы передана ExitAction.__call__.

. Если анализатор завершает работу без ошибки, ваш код продолжает цикл while без выхода.Единственный выход из этого цикла - парсер выдает ошибку.

С этой ошибкой парсер печатает использование и сообщение, а затем вызывает sys.exit(2).Команда -h вызовет действие -h.Он печатает справку, а также вызывает sys.exit(2).

. Хотя argparse можно использовать для анализа строк input, он не предназначен для этой задачи.Обычно он анализирует sys.argv[1:].Тем не менее, команды ipython magic часто используют argparse для разбора параметров, ведя себя подобно командам оболочки sys.

argparse не размещает позиционные аргументы на основе значения - он размещает их строго на позиции,Если вы определяете и read, и exit, то первая строка переходит на read независимо от ее значения, а вторая на exit.(См. Мой недавний ответ: https://stackoverflow.com/a/53605878/901925)

Помеченные (optionals) выделяются в зависимости от значения. Но чтобы использовать их, вы должны давать такие команды, как

- читать foo - выход из бара

0 голосов
/ 06 декабря 2018

Вы не привязываете команды к буквенным строкам read и exit;это не то, как argparse работает.Вместо этого вы определяете синтаксический анализатор, который принимает два произвольных слова и связывает первое с read, а второе с exit.Ваш закомментированный код будет выводиться независимо от того, какое одиночное слово вы набрали, а не только exit.Без комментариев парсер ожидает два слова и выдает ошибку, когда вы предоставляете только одно.

Если вы собираетесь (ab) использовать argparse таким образом, я предлагаю вам прочитать о подкомандах вдокументация.

...