當然,在之前的系列中,我已介紹如何給 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的專欄