Python с использованием argparse с cmd
Есть ли способ использовать argparse
модуль подключен как интерпретатор для каждой подсказки в интерфейсе, наследующемся от cmd
?
Я хотел бы, чтобы мой интерфейс cmd интерпретировал типичный line
Параметр таким же образом можно интерпретировать параметры и аргументы, переданные во время выполнения в оболочке bash, используя необязательные аргументы с -
а также позиционные аргументы.
2 ответа
Прямой путь был бы создать argparse
парсер и парсинг line.split()
в пределах вашей функции, expect
ИНГ SystemExit
если указаны неверные аргументы (parse_args()
звонки sys.exit()
когда он находит недействительные аргументы).
class TestInterface(cmd.Cmd):
__test1_parser = argparse.ArgumentParser(prog="test1")
__test1_parser.add_argument('--bar', help="bar help")
def help_test1(self): self.__test1_parser.print_help()
def do_test1(self, line):
try:
parsed = self.__test1_parser.parse_args(line.split())
except SystemExit:
return
print("Test1...")
print(parsed)
Если переданы неверные аргументы, parse_args()
выведет ошибки, и программа вернется к интерфейсу без выхода.
(Cmd) test1 --unk
usage: test1 [-h] [--bar BAR]
test1: error: unrecognized arguments: --unk
(Cmd)
Все остальное должно работать так же, как обычный argparse
вариант использования, также поддерживая все cmd
функциональность (справочные сообщения, список функций и т. д.)
Источник: https://groups.google.com/forum/
Другой способ, который упрощает настройку выше, использует декоратор ниже:
class ArgparseCmdWrapper:
def __init__(self, parser):
"""Init decorator with an argparse parser to be used in parsing cmd-line options"""
self.parser = parser
self.help_msg = ""
def __call__(self, f):
"""Decorate 'f' to parse 'line' and pass options to decorated function"""
if not self.parser: # If no parser was passed to the decorator, get it from 'f'
self.parser = f(None, None, None, True)
def wrapped_f(*args):
line = args[1].split()
try:
parsed = self.parser.parse_args(line)
except SystemExit:
return
f(*args, parsed=parsed)
wrapped_f.__doc__ = self.__get_help(self.parser)
return wrapped_f
@staticmethod
def __get_help(parser):
"""Get and return help message from 'parser.print_help()'"""
f = tempfile.SpooledTemporaryFile(max_size=2048)
parser.print_help(file=f)
f.seek(0)
return f.read().rstrip()
Это упрощает определение дополнительных команд, когда они требуют дополнительных parsed
параметр, который содержит результат успешного parse_args()
, Если есть недопустимые аргументы, функция никогда не вводится, все обрабатывается декоратором.
__test2_parser = argparse.ArgumentParser(prog="test2")
__test2_parser.add_argument('--foo', help="foo help")
@WrapperCmdLineArgParser(parser=__test2_parser)
def do_test2(self, line, parsed):
print("Test2...")
print(parsed)
Все работает как оригинальный пример, в том числе argparse
сгенерированные справочные сообщения - без необходимости определять help_command()
функция.
Источник: https://codereview.stackexchange.com/questions/134333/using-argparse-module-within-cmd-interface
Ну, один из способов сделать это - переопределить cmd
"s default
метод и использовать его для анализа строки с argparse
, потому что все команды без do_
метод в вашем подклассе cmd.Cmd провалится, чтобы использовать default
метод. Обратите внимание на дополнительные _
до do_test
чтобы избежать его использования в качестве cmd
команда.
import argparse
import cmd
import shlex
class TestCLI(cmd.Cmd):
def __init__(self, **kwargs):
cmd.Cmd.__init__(self, **kwargs)
self.parser = argparse.ArgumentParser()
subparsers = self.parser.add_subparsers()
test_parser = subparsers.add_parser("test")
test_parser.add_argument("--foo", default="Hello")
test_parser.add_argument("--bar", default="World")
test_parser.set_defaults(func=self._do_test)
def _do_test(self, args):
print args.foo, args.bar
def default(self, line):
args = self.parser.parse_args(shlex.split(line))
if hasattr(args, 'func'):
args.func(args)
else:
cmd.Cmd.default(self, line)
test = TestCLI()
test.cmdloop()
argparse
делает sys.exit
если он сталкивается с неизвестными командами, то вам придется переопределить или обезьяна исправить ваш ArgumentParser
"s error
способ вызвать исключение вместо выхода и обработать его в default
метод, чтобы остаться в cmd
Командный цикл.
Я бы посоветовал вам взглянуть на скалу, которая позволяет вам писать команды, которые могут автоматически использоваться как argparse
а также cmd
команды, что довольно аккуратно. Он также поддерживает команды загрузки из setuptools
точки входа, которые позволяют распределять команды в виде плагинов для вашего приложения. Обратите внимание, что cliff
использования cmd2
, который cmd
более сильный кузен, но вы можете заменить его cmd
как cmd2
был разработан в качестве замены для замены cmd
,