Python 基于argparse的调用函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27529610/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 01:56:04  来源:igfitidea点击:

Call function based on argparse

pythonargparse

提问by f0rd42

I'm new to python and currently playing with it. I have a script which does some API Calls to an appliance. I would like to extend the functionality and call different functions based on the arguments given when calling the script.

我是 python 的新手,目前正在使用它。我有一个脚本,它对设备执行一些 API 调用。我想扩展功能并根据调用脚本时给出的参数调用不同的函数。

Currently I have the following:

目前我有以下几点:

parser = argparse.ArgumentParser()
parser.add_argument("--showtop20", help="list top 20 by app",
                    action="store_true")
parser.add_argument("--listapps", help="list all available apps",
                    action="store_true")
args = parser.parse_args()

I also have a

我也有一个

def showtop20():
    .....

and

def listapps():
....

How can I call the function (and only this) based on the argument given? I don't want to run

我怎样才能根据给定的参数调用函数(只有这个)?我不想跑

if args.showtop20:
   #code here

if args.listapps:
   #code here

as I want to move the different functions to a module later on keeping the main executable file clean and tidy.

因为我想稍后将不同的功能移动到一个模块中,以保持主可执行文件干净整洁。

采纳答案by Hannes Ovrén

Since it seems like you want to run one, and only one, function depending on the arguments given, I would suggest you use a mandatory positional argument ./prog command, instead of optional arguments (./prog --command1or ./prog --command2).

由于您似乎想根据给定的参数运行一个且仅运行一个函数,因此我建议您使用强制位置参数./prog command,而不是可选参数(./prog --command1./prog --command2)。

so, something like this should do it:

所以,像这样的事情应该这样做:

FUNCTION_MAP = {'top20' : my_top20_func,
                'listapps' : my_listapps_func }

parser.add_argument('command', choices=FUNCTION_MAP.keys())

args = parser.parse_args()

func = FUNCTION_MAP[args.command]
func()

回答by Juan Diego Godoy Robles

If your functions are "simple enough" take adventage of typeparameter https://docs.python.org/2.7/library/argparse.html#type

如果您的函数“足够简单”,请利用type参数https://docs.python.org/2.7/library/argparse.html#type

type= can take any callable that takes a single string argument and returns the converted value:

type= 可以接受任何接受单个字符串参数并返回转换后的值的可调用对象:

In your example (even if you don't need a converted value):

在您的示例中(即使您不需要转换值):

parser.add_argument("--listapps", help="list all available apps",
                    type=showtop20,
                    action="store")

This simple script:

这个简单的脚本:

import argparse

def showtop20(dummy):
    print "{0}\n".format(dummy) * 5

parser = argparse.ArgumentParser()
parser.add_argument("--listapps", help="list all available apps",
                    type=showtop20,
                    action="store")
args = parser.parse_args()

Will give:

会给:

# ./test.py --listapps test
test
test
test
test
test
test

回答by hpaulj

There are lots of ways of skinning this cat. Here's one using action='store_const'(inspired by the documented subparser example):

有很多方法可以给这只猫剥皮。这是一个使用action='store_const'(受文档化的子解析器示例启发):

p=argparse.ArgumentParser()
p.add_argument('--cmd1', action='store_const', const=lambda:'cmd1', dest='cmd')
p.add_argument('--cmd2', action='store_const', const=lambda:'cmd2', dest='cmd')

args = p.parse_args(['--cmd1'])
# Out[21]: Namespace(cmd=<function <lambda> at 0x9abf994>)

p.parse_args(['--cmd2']).cmd()
# Out[19]: 'cmd2'
p.parse_args(['--cmd1']).cmd()
# Out[20]: 'cmd1'

With a shared dest, each action puts its function (const) in the same Namespace attribute. The function is invoked by args.cmd().

使用 shared dest,每个操作都将其函数 ( const) 放在相同的 Namespace 属性中。该函数由 调用args.cmd()

And as in the documented subparsers example, those functions could be written so as to use other values from Namespace.

就像在文档化的子解析器示例中一样,可以编写这些函数以使用命名空间中的其他值。

args = parse_args()
args.cmd(args)

For sake of comparison, here's the equivalent subparsers case:

为了比较,这里是等效的子解析器案例:

p = argparse.ArgumentParser()
sp = p.add_subparsers(dest='cmdstr')
sp1 = sp.add_parser('cmd1')
sp1.set_defaults(cmd=lambda:'cmd1')
sp2 = sp.add_parser('cmd2')
sp2.set_defaults(cmd=lambda:'cmd2')

p.parse_args(['cmd1']).cmd()
# Out[25]: 'cmd1'

As illustrated in the documentation, subparsers lets you define different parameter arguments for each of the commands.

如文档中所示,子解析器允许您为每个命令定义不同的参数参数。

And of course all of these addargument or parser statements could be created in a loop over some list or dictionary that pairs a key with a function.

当然,所有这些add参数或解析器语句都可以在某个列表或字典的循环中创建,这些列表或字典将键与函数配对。

Another important consideration - what kind of usage and help do you want? The different approaches generate very different help messages.

另一个重要的考虑因素 - 您想要什么样的用法和帮助?不同的方法会生成非常不同的帮助消息。

回答by Six

At least from what you have described, --showtop20and --listappssound more like sub-commands than options. Assuming this is the case, we can use subparsers to achieve your desired result. Here is a proof of concept:

至少从你所描述的东西,--showtop20--listapps声音更像选项的子命令。假设是这种情况,我们可以使用子解析器来实现您想要的结果。这是一个概念证明:

import argparse
import sys

def showtop20():
    print('running showtop20')

def listapps():
    print('running listapps')

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()

# Create a showtop20 subcommand    
parser_showtop20 = subparsers.add_parser('showtop20', help='list top 20 by app')
parser_showtop20.set_defaults(func=showtop20)

# Create a listapps subcommand       
parser_listapps = subparsers.add_parser('listapps', help='list all available apps')
parser_listapps.set_defaults(func=listapps)

# Print usage message if no args are supplied.

# NOTE: Python 2 will error 'too few arguments' if no subcommand is supplied.
#       No such error occurs in Python 3, which makes it feasible to check
#       whether a subcommand was provided (displaying a help message if not).
#       argparse internals vary significantly over the major versions, so it's
#       much easier to just override the args passed to it.

if len(sys.argv) <= 1:
    sys.argv.append('--help')

options = parser.parse_args()

# Run the appropriate function (in this case showtop20 or listapps)
options.func()

# If you add command-line options, consider passing them to the function,
# e.g. `options.func(options)`