当然,在之前的系列中,我已介绍如何给 Python 脚本传参,当然,今天不会继续介绍这么无聊的东东。首先使用 python 的sys.argv 传参的话,就固定了参数的个数、顺序以及格式,这么死的规定如何性感?
I have a dream , to make my code much sexer ! 今天我们简单介绍一下如何更加随性的给 python 脚本传参。效果如下:
long@zhouyl:/tmp$ python arg.py -h NAME: project with user set arguments SYNOPSIS: [python] arg.py [OPTION]... DESCRIPTION: -h, --Help Print this help (work alone, won't work while be mixed with other argu) -a, --testa a value -b, --testb b value AUTHOR: Zhou Yunlong <reaper888@yeah.net> long@zhouyl:/tmp$ python arg.py -a 1 -b=2 Argument a values: 1 Argument b values: 2 long@zhouyl:/tmp$ python arg.py -a 1 -b='/home/long' Argument a values: 1 Argument b values: /home/long
我们可以看到,有了很Linux 的help 帮助信息 ,还可以随便传递参数。是不是很好玩,下面简单介绍:
一、 如何获取不定个数的参数
当然,万变不离其宗,偶们还是得老老实实的靠 sys.argv 来传递参数,但是我们之前介绍的博文中是这样传递参数的:
(script, first_argu, second_argu)= sys.argv
这样固然简单易用,但是问题就是参数的数量、顺序、格式都根据脚本中接收代码确定下来,没有易用性。
那么我们如何解决带不定数量的参数呢? 我使用的方法很简单, 不使用固定数量的变量来接收参数,来一个哥接一个,全给你放到列表中:
def add_sys_argv(): arg_list = [] for i in range(1, len(sys.argv)): arg_list.append(sys.argv[i]) return arg_list
那么,这个函数获取并返回的列表中存放的都是用户传递进来的参数呢。所以,一切就变得更加简单了。
二、 查找参数
很多的Linux 命令中都可以不固定参数的顺序,且一般都是遵循 “ -[OPTION] VALUE ” 的顺序,这样传进来的参数,哇哦,好判断,我只要使用 " if ‘-a‘ in argu_list " 即可。
但是我想要它更性感,不知你有没有使用过 “ -[OPTION]=VALUE ” 这样的赋值, 我感觉这样的赋值也挺好,不会弄乱,看起来也很方便。而对于参数列表中接收到的 "-a=123"参数项,只使用 " if ‘-a‘ in argu_list " 就不能找到咯,我们需要使用 字符串的 find 方法。
查找函数很简单:
def check_arument_in(argu, arg_list): for i in range(0, len(arg_list)): if arg_list[i].find(argu) != -1 : return True return False
对于列表中的每一项进行find ,如果找到返回 True ,如果整个列表都找不到则返回 False。
对于参数的值的获取,因为我想要 “ -[OPTION] VALUE ” 和 “ -[OPTION]=VALUE ” 在这两种赋值方法都可以使用,所以使用check_arument_in 查找到后还需要对此项进行查找有没有 ‘=‘ ,如果有就在此项中得到赋值,如果没有‘=‘ 赋值就是列表的下一个值:
def get_argument_value(argu, arg_list): for i in range(0, len(arg_list)): if arg_list[i].find(argu) != -1 : if arg_list[i].find('=') != -1 : a_argu = arg_list[i].split("=")[1] if len(a_argu) == 0: return 0 else: return a_argu elif (i+1) <= len(arg_list): a_argu = arg_list[i+1] return a_argu else: print "it seems that argument is error" return 0
三、 对参数做出相应处理
进入脚本之后我们首先使用一个函数对参数进行判断:
def get_user_argu(): sys_arg_list = add_sys_argv() if '-h' in sys_arg_list and len(sys_arg_list) == 1: # 如果参数只有一个,且是"-h" 的话,调用打印help 信息的函数 print_usage() if check_arument_in('-a', sys_arg_list): # 此后就需要对你关心的参数项进行查找并获取,如果有则做相应的操作。 a_argu = get_argument_value('-a', sys_arg_list) print "Argument a values: %s" % a_argu if check_arument_in('-b', sys_arg_list): b_argu = get_argument_value('-b', sys_arg_list) print "Argument b values: %s" % b_argu
对于打印help 信息的函数就更简单了:
def print_usage(): print """NAME: project with user set arguments \n SYNOPSIS: [python] arg.py [OPTION]... \n DESCRIPTION: -h, --Help Print this help (work alone, won't work while be mixed with other argu) -a, --testa a value -b, --testb b value AUTHOR: Zhou Yunlong <reaper888@yeah.net> """ sys.exit()
四、 完整程序赏析
整个示例 arg.py 很简单:
#!/usr/bin/python import sys def add_sys_argv(): leng = len(sys.argv) arg_list = [] for i in range(1, leng): arg_list.append(sys.argv[i]) return arg_list def check_arument_in(argu, arg_list): for i in range(0, len(arg_list)): if arg_list[i].find(argu) != -1 : return True return False #print arg_list def get_argument_value(argu, arg_list): for i in range(0, len(arg_list)): if arg_list[i].find(argu) != -1 : if arg_list[i].find('=') != -1 : a_argu = arg_list[i].split("=")[1] if len(a_argu) == 0: return 0 else: return a_argu elif (i+1) <= len(arg_list): a_argu = arg_list[i+1] return a_argu else: print "it seems that argument is error" return 0 def print_usage(): print """NAME: project with user set arguments \n SYNOPSIS: [python] arg.py [OPTION]... \n DESCRIPTION: -h, --Help Print this help (work alone, won't work while be mixed with other argu) -a, --testa a value -b, --testb b value AUTHOR: Zhou Yunlong <reaper888@yeah.net> """ sys.exit() def get_user_argu(): sys_arg_list = add_sys_argv() print sys_arg_list if '-h' in sys_arg_list and len(sys_arg_list) == 1: print_usage() if check_arument_in('-a', sys_arg_list): a_argu = get_argument_value('-a', sys_arg_list) print "Argument a values: %s" % a_argu if check_arument_in('-b', sys_arg_list): b_argu = get_argument_value('-b', sys_arg_list) print "Argument b values: %s" % b_argu get_user_argu()
运行结果在上面已经展示过了,但是因为示例过于简单,还未对参数的内容进行判断,所以可能会出现这样的错误:
long@zhouyl:/tmp$ python arg.py -a -b='/home/long' Argument a values: -b=/home/long
所以,如果你想要你的程序更加完整以及安全,就需要对参数进行更多的判断以及审核
五、 关于大型程序的参数处理
对于一些大型程序中使用的参数处理并不是上面我这样,而且很好玩,很适宜我们学习。
这里我们以GCC的 gcov 为例:
static int process_args (int argc, char **argv) { int opt; while ((opt = getopt_long (argc, argv, "abcfiIhlno:puv", options, NULL)) != -1) { switch (opt) { case 'a': flag_all_blocks = 1; break; case 'b': flag_branches = 1; break; ...
我们可以看到,GCOV 中对于接收到的参数进行switch 判断,得到参数后也只是对一个flag变量进行赋值,而在程序正常处理时,则是这样:
if (flag_all_blocks) { block_t *block; arc_t *arc; int ix, jx; for (ix = jx = 0, block = line->u.blocks; block; block = block->chain) ...
flag_all_blocks 参数在程序中定义为0,只有用户带了 ‘-a‘ 参数,才会在上面的switch ...case 中将其变为1, 于是在程序运行到与之相关的部分时,只需要对 flag_all_blocks 进行判断就可以知道用户有没有携带‘-a‘ 参数,如果有则做相应处理。
==============
对于本文中的方法实属自己没事瞎玩,如果你有更好地方法,还请在留言中赐教。
转载注明出处:
CSDN博客 -- longerzone的专栏