Как собрать неуказанные параметры командной строки при использовании Python `argh`?

С библиотекой Python CLI argh Я хочу написать инструмент-обертку. Предполагается, что этот инструмент-обертка читает два варианта -a а также -b и передать все остальные параметры в функцию (которая затем вызывает обернутый инструмент UNIX с оставшимися параметрами через subprocess).

Я экспериментировал с dispatch параметр skip_unknown_args:

def wrapper(a=True, b=False):
    print("Enter wrapper")
    # 1. process a and b 
    # 2. call_unix_tool(left-over-args)

if __name__ == '__main__':
    parser = argh.ArghParser()
    argh.set_default_command(parser, wrapper)
    argh.dispatch(parser, skip_unknown_args=True)

Однако программа по-прежнему завершает работу, когда обнаруживает неизвестные параметры и не входит в функцию. wrapper по мере необходимости. Кроме того, я не знаю, где хранятся неизвестные / пропущенные аргументы, чтобы я мог передать их в инструмент UNIX.

Как я могу сказать argh идти в wrapper с пропущенными аргументами?

2 ответа

Решение

Вы не можете сделать это с skip_unknown_args=True потому что, как указал @georgexsh, argh библиотека, кажется, не ведет себя разумно с этой опцией. Однако вы можете предоставить свой собственный класс анализатора, который вставляет неизвестные аргументы в обычное пространство имен:

class ArghParserWithUnknownArgs(argh.ArghParser):
    def parse_args(self, args=None, namespace=None):
        namespace = namespace or ArghNamespace()
        (namespace_obj, unknown_args) = super(ArghParserWithUnknownArgs, self).parse_known_args(args=args, namespace=namespace)
        namespace_obj.__dict__['unknown_args'] = unknown_args
        return namespace_obj

Обратите внимание, что этот класс parse_args вызовы методов ArgParser "s parse_known_args метод!

Определив этот класс, вы можете написать код оболочки следующим образом:

def wrapper(a=True, b=False, unknown_args={}):
    print("a = %s, b = %s" % (a,b))
    print("unknown_args = %s" % unknown_args)

if __name__ == '__main__':
    parser = ArghParserWithUnknownArgs()
    argh.set_default_command(parser, wrapper)
    argh.dispatch(parser)

В вашей основной функции wrapper вы можете получить доступ ко всем неизвестным аргументам через параметр unknown_args и передать это вашей команде подпроцесса

PS: для того, чтобы сохранить справку сообщения аккуратно украсить wrapper с

@argh.arg('--unknown_args', help=argparse.SUPPRESS)

Приложение: я создал улучшенную версию парсера и скомпилировал ее в готовый к использованию модуль. Найдите это на Github.

Я считаю, что это ошибка.

когда skip_unknown_args=True, Вот namespace_obj является кортежем с объектом пространства имен и остальными аргументами:

(Pdb) p namespace_obj
    (ArghNamespace(_functions_stack=[<function wrapper at 0x105cb5e18>], a=False, b=True), ['-c'])

лежащий в основе _get_function_from_namespace_obj ожидает одинарного:

154     function = _get_function_from_namespace_obj(namespace_obj)
...
191     if isinstance(namespace_obj, ArghNamespace):

Я проверил его основной вопрос и unittest, понятия не имею, что является законным, поскольку автор ожидает, также опустил комментарий там.

почему бы не использовать argparse напрямую?

Другие вопросы по тегам