基于argparse的调用函数

时间:2014-12-17 15:55:54

标签: python argparse

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

目前我有以下内容:

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()

我也有

def showtop20():
    .....

def listapps():
....

如何根据给出的参数调用函数(并且只调用此函数)? 我不想跑

if args.showtop20:
   #code here

if args.listapps:
   #code here

因为我想稍后将不同的函数移动到模块上,以保持主要的可执行文件干净整洁。

6 个答案:

答案 0 :(得分:23)

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

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

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()

答案 1 :(得分:12)

有很多方法可以给这只猫上皮。这是使用action='store_const'的人(受到记录的subparser示例的启发):

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'

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

正如在记录的子分析器示例中那样,可以编写这些函数以便使用Namespace中的其他值。

args = parse_args()
args.cmd(args)

为了便于比较,这里是等效的子算例:

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'

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

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

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

答案 2 :(得分:6)

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

的冒险
  

type =可以接受任何带有单个字符串参数的callable   返回转换后的值:

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

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

这个简单的脚本:

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()

会给:

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

答案 3 :(得分:5)

至少从你所描述的内容来看,04-21 12:06:32.420 20288-20288/basavaraj.com.librarytools E/dalvikvm: Could not find class 'android.graphics.drawable.RippleDrawable', referenced from method android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering 04-21 12:06:37.974 20288-20288/basavaraj.com.librarytools E/AndroidRuntime: FATAL EXCEPTION: main java.lang.RuntimeException: Unable to start activity ComponentInfo{basavaraj.com.librarytools/basavaraj.com.librarytools.diff_toolbar.ToolbarColorDynamic}: java.lang.NullPointerException at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2343) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2395) at android.app.ActivityThread.access$600(ActivityThread.java:162) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:194) at android.app.ActivityThread.main(ActivityThread.java:5371) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.NullPointerException at basavaraj.com.librarytools.diff_toolbar.ToolbarColorDynamic.setToolbarColor(ToolbarColorDynamic.java:64) at basavaraj.com.librarytools.diff_toolbar.ToolbarColorDynamic.onCreate(ToolbarColorDynamic.java:42) at android.app.Activity.performCreate(Activity.java:5122) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2307) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2395)  at android.app.ActivityThread.access$600(ActivityThread.java:162)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1364)  at android.os.Handler.dispatchMessage(Handler.java:107)  at android.os.Looper.loop(Looper.java:194)  at android.app.ActivityThread.main(ActivityThread.java:5371)  at java.lang.reflect.Method.invokeNative(Native Method)  at java.lang.reflect.Method.invoke(Method.java:525)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)  at dalvik.system.NativeStart.main(Native Method) --showtop20听起来更像是子命令而不是选项。假设是这种情况,我们可以使用subparsers来实现您想要的结果。这是一个概念证明:

--listapps

答案 4 :(得分:0)

不要将您的代码用作your_script --showtop20,而是将其变成子命令your_script showtop20,然后使用click library而不是argparse。您可以定义函数作为子命令的名称,并使用修饰符指定参数:

import click

@click.group()
@click.option('--debug/--no-debug', default=False)
def cli(debug):
    print(f'Debug mode is {"on" if debug else "off"}')

@cli.command()  # @cli, not @click!
def showtop20():
    # ...

@cli.command()
def listapps():
    # ...

请参见https://click.palletsprojects.com/en/master/commands/

答案 5 :(得分:0)

# based on parser input to invoke either regression/classification plus other params

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--path", type=str)
parser.add_argument("--target", type=str)
parser.add_argument("--type", type=str)
parser.add_argument("--deviceType", type=str)    

args = parser.parse_args()
df = pd.read_csv(args.path)
df = df.loc[:, ~df.columns.str.contains('^Unnamed')]
if args.type == "classification":
    classify = AutoML(df, args.target, args.type, args.deviceType)
    classify.class_dist()
    classify.classification()

elif args.type == "regression":
    reg = AutoML(df, args.target, args.type, args.deviceType)
    reg.regression()

else:
    ValueError("Invalid argument passed")


# Values passed as : python app.py --path C:\Users\Abhishek\Downloads\adult.csv --target income --type classification --deviceType GPU