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 <[email protected]>

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 <[email protected]>
"""
    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 <[email protected]>
"""
    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的專欄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章