2013-01-25 49 views
0

我需要编写一个命令行应用程序,例如shell。所以它会包含命令等等。事情是我不知道如何将参数传递给模块中的函数。例如:Python - 在命令行应用程序中传递参数

用户写入:function1 folder1 程序现在应该将'folder1'参数传递给function1函数并运行它。但也有支持其他功能使用不同的参数例如:

用户输入:函数2文件夹2 --exampleparam

如何使这个工作?我的意思是,我只需要编写一个模块,将其导入到python中,然后使用python控制台,但事实并非如此。我需要一个脚本,它接受命令输入并运行它。

我试图使用eval(),但是这并不能解决params问题。或者也许它确实存在,但我没有看到它?

回答

6

问题的第一部分 - 解析命令行 - 可以用argparse来解决。

第二部分 - 将函数的字符串名称转换为函数调用 - 可以使用exec或从字符串映射到函数对象的调度字典完成。

我会建议使用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_inputstdin获取字符串。然后,我们可以解析字符串以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 

main.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 module,如评论中提到的@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's excellent tutorial.


运行上述代码产生这样的结果:

% 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 
+0

第二部分,请看'cmd'模块。 – chepner

+0

这适用于我,但我仍然无法弄清楚如何从另一个脚本实际启动命令。如果我把它放到模块中的一个函数中,并像这样调用它:module.function,什么都不会发生。但是,如果我这样做:module.function 1,我得到一个语法错误。由于该函数没有任何参数,因此没有必要使用参数module.function(param)调用它。 我是Python的新手,并且不幸的是还没有真正掌握它。 –

+0

试试'import module; module.function()'调用'module'中定义的'function'。 – unutbu

0

看看optparse。这可以帮助将外壳样式参数传递给python脚本。

更新: 显然optparse已被弃用,argparse现在是解析命令行参数的首选选项。

0
import sys 

def main(arg): 
    return arg 

print main(sys.argv[1]) 

其中sys.argv中[0]是你正在运行的.py文件,以及所有的那些后,这将是每个参数。你可以检查列表的长度,然后遍历它,并根据需要解析它们,并将正确的东西传递给每个函数。

1

看看optparse模块在Python中。这正是你所需要的东西:

http://docs.python.org/2/library/optparse.html 

也可以编写自己的自定义选择的解析器(简约虽然)

def getopts(argv): 
    opts = {} 
    while argv: 
     if argv[0][0] == '-': # find "-name value" pairs 
     opts[argv[0]] = argv[1] # dict key is "-name" arg 
     argv = argv[2:] 
     else: 
     argv = argv[1:] 
    return opts 

if __name__ == '__main__': 
from sys import argv # example client code 
myargs = getopts(argv) 
# DO something based on your logic here 

但如果你的脚本需要在Python 3的运行,并超越,你需要考虑argparse模块。\

希望有所帮助。

2

optparse因为蟒2.7已被弃用无论如何,argparse更加灵活。 unutbu的方法是安全的,但如果你提供白名单,我建议你让用户知道哪些功能是接受

dispatch = { 
    'foo': foo,  
    'bar': bar, 
} 

parser = argparse.ArgumentParser() 
parser.add_argument('function', choices=dispatch.keys()) 

FYI:如果解析是不是太复杂,docopt貌似很不错的软件包