我是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
因为我想稍后将不同的函数移动到模块上,以保持主要的可执行文件干净整洁。
答案 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():
# ...
答案 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