这里是python的新手 - 我想创建一个命令行应用程序,用户将在其中键入输入我将解析它并执行一些命令 - 在以下行中的内容:
try:
while True:
input = raw_input('> ')
# parse here
except KeyboardInterrupt:
pass
用户应该键入init /path/to/dir
之类的命令。我可以使用argparse
来解析这些吗?我的方式太粗糙了吗?
答案 0 :(得分:2)
您可以查看cmd lib:http://docs.python.org/library/cmd.html
如果您想自己解析,可以使用split
来标记用户输入,并根据令牌执行命令,如下所示:
try:
while True:
input = raw_input('> ')
tokens = input.split()
command = tokens[0]
args = tokens[1:]
if command == 'init':
# perform init command
elif command == 'blah':
# perform other command
except KeyboardInterrupt:
pass
答案 1 :(得分:2)
arparse是您提出建议的完美解决方案。这些文档编写得很好,并展示了如何简单地调用它的几十个例子。请记住,它希望默认读取sys.argv,所以当你调用parse_args时,你想给它args(https://docs.python.org/2.7/library/argparse.html?highlight=argparse#the-parse-args-method)。
唯一的缩小是argparse期望这些项目在"参数"格式,表示以破折号为前缀。
>>> import argparse
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('-init', nargs=1)
>>> parser.parse_args('-init /path/to/something'.split())
Namespace(init="/path/to/something")
答案 2 :(得分:0)
这取决于你想要做什么,但你可以让你的脚本使用ipython(交互式python)。例如:
#!/bin/ipython -i
def init(path_to_dir):
print(path_to_dir)
用法:盯着剧本后,
的init(" pathToFile.txt&#34)
您正在交互式python会话中运行,因此您可以获得难以手动实现的标签完成等功能。另一方面,你坚持使用python语法。这取决于你的申请。
答案 3 :(得分:0)
我做的是:
# main
parser = Parser('blah')
try:
while True:
# http://stackoverflow.com/a/17352877/281545
cmd = shlex.split(raw_input('> ').strip())
logging.debug('command line: %s', cmd)
try:
parser.parse(cmd)
except SystemExit: # DUH http://stackoverflow.com/q/16004901/281545
pass
except KeyboardInterrupt:
pass
解析器的位置:
class Parser(argparse.ArgumentParser):
def __init__(self, desc, add_h=True):
super(Parser, self).__init__(description=desc, add_help=add_h,
formatter_class=argparse.
ArgumentDefaultsHelpFormatter)
# https://docs.python.org/dev/library/argparse.html#sub-commands
self.subparsers = subparsers = self.add_subparsers(
help='sub-command help')
# http://stackoverflow.com/a/8757447/281545
subparsers._parser_class = argparse.ArgumentParser
from watcher.commands import CMDS
for cmd in CMDS: cmd()(subparsers)
def parse(self, args):
return self.parse_args(args)
一个命令(CMDS=[watch.Watch]
):
class Watch(Command):
class _WatchAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
# here is the actual logic of the command
logging.debug('%r %r %r' % (namespace, values, option_string))
setattr(namespace, self.dest, values)
Sync.addObserver(path=values)
CMD_NAME = 'watch'
CMD_HELP = 'Watch a directory tree for changes'
ARGUMENTS = {'path': Arg(hlp='Path to a directory to watch. May be '
'relative or absolute', action=_WatchAction)}
其中:
class Command(object):
"""A command given by the users - subclasses must define the CMD_NAME,
CMD_HELP and ARGUMENTS class fields"""
def __call__(self, subparsers):
parser_a = subparsers.add_parser(self.__class__.CMD_NAME,
help=self.__class__.CMD_HELP)
for dest, arg in self.__class__.ARGUMENTS.iteritems():
parser_a.add_argument(dest=dest, help=arg.help, action=arg.action)
return parser_a
class Arg(object):
"""Wrapper around cli arguments for a command"""
def __init__(self, hlp=None, action='store'):
self.help = hlp
self.action = action
到目前为止只尝试了一个命令,所以这是相当未经测试的。我使用了评论中的shlex和subparsers提示。我看了一下@ jh314建议的cmd模块,但是并没有完全理解它 - 但是我认为它是工作的工具 - 我对使用cmd模块做代码的代码感兴趣。/ p>