首页 > 代码库 > python 学习笔记 11 -- 使用参数使你的程序变得更性感

python 学习笔记 11 -- 使用参数使你的程序变得更性感

当然,在之前的系列中,我已介绍如何给 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的专栏