使用argparse输出调用函数
我现在的代码是这样的。它让我可以解析我程序脚本接收到的多个参数。有没有更接近“最佳实践”的其他方法呢?我只见过关于如何设置argparse
的代码,但没有看到实际使用它输出的代码。
def useArguments():
x = 0
while x <= 5:
if x == 0:
if args.getweather != None:
getWeather(args.getweather)
if x == 1:
if args.post != None:
post(args.post)
if x == 2:
if args.custompost != None:
custompost(args.custompost)
if x == 3:
if args.list != None:
listAccounts(args.list)
if x == 4:
if args.add != None:
addAccount(args.add[0])
if x == 5:
if args.edit != None:
editAccount(args.edit[0])
x = x + 1
if __name__ == '__main__':
updateConfig()
parser = argparse.ArgumentParser(description='Post Yahoo weather to Twitter.', epilog="Report any bugs to example@email.com", prog='Program')
parser.add_argument('-a', '--add', nargs=1, help='Add a new account. Use the desired account name as an argument.')
parser.add_argument('-e', '--edit', nargs=1, choices=accountListSTR[:-1], help='Edit an account. Use the desired account name as an argument.')
parser.add_argument('-g', '--getweather', nargs='*', choices=accountListSTR, help='Get weather and post here. Specify account(s) as argument. Use "all" for all accounts. If you specify multiple accounts, separate by a space NOT a comma.')
parser.add_argument('-p', '--post', nargs='*', choices=accountListSTR, help='Post weather to Twitter. Specify account(s) as argument. Use "all" for all accounts. If you specify multiple accounts, separate by a space NOT a comma.')
parser.add_argument('-c', '--custompost', nargs=2, help='Post a custom message. Specify an account then type the message. Make sure you use "" around the message. Use "all" for all accounts.')
parser.add_argument('-l', '--list', action='store_const', const='all', help='List all accounts.')
parser.add_argument('--version', action='version', version='%(prog)s 0.3.3')
args = parser.parse_args()
useArguments()
3 个回答
除了 --version
这个选项外,其他你提供的操作更适合被当作“子命令”来处理。
我对 argparse 的具体情况不太了解,因为我还没试过 Python 2.7,但你可以看看 svn
命令作为一个例子,下面是一些命令行的伪代码:
myprog [--version] <command> [<command opts>...]
这里的 <command>
是指:
add|edit|getweather|post|custompost|list
而 <command opts>
是特定于那个命令的选项。使用 optparse(它的功能类似),这意味着当你调用 parse_args
时,你的命令会被返回到 args
中,这样你就可以做类似这样的事情:
opts, args = parser.parse_args()
if opts.version:
...
else:
getattr("do_" + args[0])(*args[1:])
我发现这种模式在调试时特别有用,因为我可以通过命令行访问内部函数,并传递各种参数进行测试。根据你自己的项目需要,调整命令处理程序的选择。
请查看这个链接:http://docs.python.org/library/argparse.html#sub-commands:
处理子命令的一个特别有效的方法是结合使用
add_subparsers()
方法和set_defaults()
的调用,这样每个子解析器就知道应该执行哪个 Python 函数。
简单来说:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
weather_parser = subparsers.add_parser('get-weather')
weather_parser.add_argument('--bar')
weather_parser.set_defaults(function=get_weather) # !
args = parser.parse_args(['get-weather', '--bar', 'quux'])
print args.function(args)
在这里,我们为命令 get-weather
创建了一个子解析器,并将函数 get_weather
分配给它。
需要注意的是,文档中提到的关键字/属性叫 func
,但实际上从 argparse 1.1 开始,它应该是 function
。
生成的代码有点啰嗦,所以我发布了一个小工具包 "argh",可以让事情变得更简单,比如:
parser = argparse.ArgumentParser()
add_commands(parser, [get_weather])
print dispatch(parser, ['get-weather', '--bar', 'quux'])
"Argh" 能做更多的事情,但我就不在这里多说了,让 Stack Overflow 来解答吧。:-)
你可以为一个参数提供自定义的动作,具体方法是:
传递一个实现了动作API的对象。最简单的方式是扩展 argparse.Action,并提供一个合适的
__call__
方法。这个__call__
方法需要接受四个参数:
- parser:包含这个动作的 ArgumentParser 对象。
- namespace:将由
parse_args()
返回的命名空间对象。大多数动作会在这个对象上添加一个属性。- values:与命令行参数相关的值,已经应用了任何类型转换。(类型转换是通过
add_argument()
的 type 关键字参数指定的。)- option_string:用于调用这个动作的选项字符串。这个 option_string 参数是可选的,如果这个动作与位置参数关联,则不会出现。