问题的第一部分——解析命令行——可以用argparse来解决。
第二部分——将函数的字符串名称转换为函数调用——可以使用exec或从字符串映射到函数对象的调度 dict 来完成。
我建议不要使用exec
它,因为允许用户从命令行调用任意 Python 函数可能很危险。相反,制作一个允许功能的白名单:
import argparse
def foo(path):
print('Running foo(%r)' % (path, ))
def bar(path):
print('Running bar(%r)' % (path, ))
dispatch = {
'foo': foo,
'bar': bar,
}
parser = argparse.ArgumentParser()
parser.add_argument('function')
parser.add_argument('arguments', nargs='*')
args = parser.parse_args()
dispatch[args.function](*args.arguments)
% test.py foo 1
Running foo('1')
% test.py bar 2
Running bar('2')
% test.py baz 3
KeyError: 'baz'
当命令输入到命令行本身时,上述方法有效。如果命令被输入到stdin
中,那么我们需要做一些不同的事情。
一个简单的方法是调用raw_input
从stdin
. 然后我们可以使用 argparse 解析字符串,就像我们上面所做的那样:
shmod.py:
import argparse
def foo(path):
print('Running foo(%r)' % (path, ))
def bar(path):
print('Running bar(%r)' % (path, ))
dispatch = {
'foo': foo,
'bar': bar,
}
def parse_args(cmd):
parser = argparse.ArgumentParser()
parser.add_argument('function')
parser.add_argument('arguments', nargs='*')
args = parser.parse_args(cmd.split())
return args
主.py:
import shmod
while True:
cmd = raw_input('> ')
args = shmod.parse_args(cmd)
try:
shmod.dispatch[args.function](*args.arguments)
except KeyError:
print('Invalid input: {!r}'.format(cmd))
另一种更复杂的处理方法是使用cmd 模块,正如@chepner 在评论中提到的那样。
from cmd import Cmd
class MyInterpreter(Cmd):
prompt = '> '
def do_prompt(self, line):
"Change the interactive prompt"
self.prompt = line + ': '
def do_EOF(self, line):
return True
def do_foo(self, line):
print('Running foo {l}'.format(l=line))
def do_bar(self, line):
print('Running bar {l}'.format(l=line))
if __name__ == '__main__':
MyInterpreter().cmdloop()
有关如何使用 cmd 模块的更多信息,请参阅Doug Hellman 的优秀教程。
运行上面的代码会产生如下结果:
% test.py
> foo 1
Running foo 1
> foo 1 2 3
Running foo 1 2 3
> bar 2
Running bar 2
> baz 3
*** Unknown syntax: baz 3