python之OptionParser

来源:互联网 发布:比特彗星设置 知乎 编辑:程序博客网 时间:2024/06/03 18:02

簡介: 
optparse 是一個能夠讓程式設計人員輕鬆設計出簡單明瞭、易於使用、符合標準的 Unix 命令列程式的 Python套件。開始學習 Python之後,我常常會寫一些小程式來處理日常的工作;漸漸地,我發現無法處理參數的程式的彈性有限,於是就開始為我的程式加上解讀命令列參數的功能。在發現這個套件之前,我總是覺得解讀命令列不難,但是要做到像標準Unix 命令那樣完善的使用者互動和錯誤處置,可就不是一件簡單的事了!某天在 Python Library Reference中發現這個套件,真是如獲至寶!從此不用再為解讀參數煩惱,可以更專注在解決問題上了! 

如果對於 optparse套件有興趣,想快速入門的話,可以直接看"基本使用流程"小節,然後再看後面的一些介紹與說明;當然啦!想獲得最詳細的資訊,就只有自己去看Python Library Reference 囉~ 

就以下列命令來解釋一些術語,myprog 是命令的名字, $ 是命令列提示符號: 

$myprog -f thefile.txt -s xyz a1 a2 a3 


●argument: 
使用者在命令後面所輸入的字串。以本例來說,"-f", "thefile.txt", "-s", "xyz", "a1", "a2","a3" 都是 argument。在 Python 中,可以使用 sys.argv[1:] 來得到命令列傳進來的argument。為什麼是 sys.argv[1:] ,而不是 sys.argv呢?因為命令列收到完整的參數還要加上一個命令本身的檔名,以本例來說, sys.argv應該是: 

["myprog", "-f", "thefile.txt", "-s", "xyz", "a1", "a2","a3"] 


所以如果要得到去除命令本身的檔名以後的參數列,就要靠 sys.argv[1:] 了。 

●option: 
一些傳遞給命令的額外 argument,以改變程式的行為。以本例來說, "-f", "-s" 就是option。 
有幾種 option 的寫法,在 Unix 系統上的傳統寫法是 "-" 後跟著一個字母,例如 "-f", "-s";以及 "-f-s", 和 "-fs", 在 Unix 系統上都可以被接受。 GNU project 使用另一種方式,以 "--" 後面跟著一串由"-" 分開的字串,例如 "--file-for-log"。Python 的 optparse 套件只接受以上所提的兩種 option格式。 

顧名思義, option 應該是可有可無的,即使命令中沒有任何的option,程式也應該能夠正確地執行。如果程式需要使用者輸入某些資料才能運作,那麼也應該是使用 positionalargument 才對。 

●option argument: 
緊跟隨在 option 後的 argument,就是 option argument。以本例來說, "thefile.txt","xyz" 都是 option argument。指定 option argument 有兩種寫法, "-f thefile" 和"-fthefile", optparse 套件都接受。 

option 亦可以沒有 option argument,意即 option 單獨存在。這樣的 option 通常做為旗標(flag) 用,代表某個功能的開啟或是關閉。 

●positional argument: 
當一個 argument list 被解讀完後,剩下的就是 positional argument 了!以本例來說, "a1","a2", "a3" 就是 positionalargument。通常被用在"使用者必須輸入"的資訊上。 

●required option: 
一個有點讓人覺得矛盾的名詞:既然是 "option" (選擇),又怎麼會是 "required" (必須)的呢? optparse套件不對這種 option 做出任何的限制或是協助。詳情可以參閱 Python Library Reference 6.20.5的範例程式。 

基本使用流程: 

》1.產生一個 optparse.OptionParser 的物件。可以在產生時將"程式的命令列說明" (usage) 做為參數,交給OptionParser 的建構子: 

from optparse import OptionParser 
MSG_USAGE = "myprog[ -f <filename>][-s <xyz>] arg1[,arg2...]" 
optParser = OptionParser(MSG_USAGE) 


》2.呼叫 OptionParser.add_option() 加入接受的option: 

optParser.add_option("-f", 
"--file", 
action = "store", 
type = "string", 
dest = "fileName") 


add_option用来加入选项,action是有store,store_true,store_false等,dest是存储的变量,default是缺省值,help是帮助提示


若有一個以上的 option,重覆上述的方式加入(注意:以下省略了 action參數): 

optParser.add_option("-s", 
"--someopt", 
type = "string", 
dest = "someopt") 


》3.呼叫 OptionParser.parse_args() 進行解讀。如果沒有傳入參數, OptionParser 預設會以sys.argv[1:] 為對象進行解讀。OptionParser.parse_args() 會傳回一個 tuple,由optparse.Values 和 一個 list 所組成。下例傳入一個假造的參數列: 

fakeArgs = ['-f', 'thefile.txt', '-s', 'xyz', 'arg1', 'arg2','arge'] 

options, args =optParser.parse_args(fakeArgs) 

print options.fileName 
print options.someopt 
print args 


最後會得到的輸出結果: 

thefile.txt 
xyz 
['arg1', 'arg2', 'arge'] 


這是一個簡單的範例,說明了 OptionParser 的一般使用方式。透過這個例子,可以看到如果為程式加入 option,並且在程式中取得 option argument 和 positionalargument。OptionParser.parse_args()還有許多用法,下面會說明一部份。 

為程式加入 flag option: 

許多的 Unix 命令擁有 "-v", "-q" 的option,代表"提供詳細訊息"或是"不顯示訊息"。要做到這一點,只要在程式中加入下列的 option: 

parser.add_option("-v", action="store_true",dest="verbose") 
parser.add_option("-q", action="store_false",dest="verbose") 
opts, args = parser.parse_args() 


第一個 add_option() 加入了一個 "-v" 的 option;如果命令列參數中出現了 "-v",則opts.verbose 將會是 True;相反的,第二個 add_option() 加入了一個 "-q"option;如果命令列參數中出現了 "-q",則 opts.verbose 將會是False,這兩者並不相悖,程式可以設計成:當收到 "-v" 時,顯示詳細訊息;當收到 "-q"時,顯示概略訊息,或完全不顯示;當兩者都沒有收到,則顯示一般的訊息。 

設定 option 的預設值: 

上述的例子都假設命令例會收到預期中的 option,那麼如果沒有 option 時,接收到的 option 值會是什麼呢?答案是None!如果想為 option 提供預設值,只要在 OptionParser.parse_args()中指定參數 default就行了: 

parser.add_option("-v", action="store_true", dest="verbose",default = True) 
parser.add_option("-q", action="store_false",dest="verbose") 
opts, args = parser.parse_args() 


上述的程式碼為程式加入了兩個 option,當 "-v" 沒有出現時, opts.verbose 預設值為 True;當 "-q"被指定時, opts.verbose 被設定為False,和上一個例子有點不同。再看下一個例子: 

parser.add_option("-v", action="store_true", dest="verbose",default=False) 
parser.add_option("-q", action="store_false",dest="verbose", default=True) 


opts.verbose 的預設值會是什麼?答案是 True,最後一個指定到同一個目標的 option預設值會被採用。 

一般的 option 亦可加入預設值: 

parser.add_option("-f", action="store", dest="fileName",default = "defaultConfig.txt") 


為程式加入說明: 

標準的 Unix 命令大多有著 "-h", "--help" 的 option,會將使用說明印出來。在OptionParser.parse_args() 中指定 "help" 參數,並指定說明的字串,就可以為這個 option加入說明了: 

parser.add_option("-v", 
action="store_true", 
dest="verbose", 
default=False, 
help="make lots of noise [default]") 


當程式收到 "-h" 或 "--help",交給 OptionParser 解讀時,會自動印出說明內容,而忽略其它的argument: 

usage: <yourscript> [options] arg1arg2 

options: 
-h, --help show this help message and exit 
-v, --verbose make lots of noise [default] 
-q, --quiet be vewwy quiet (I'm huntingwabbits) 
-fFILE, --file=FILE write output to FILE 
-mMODE, --mode=MODE interaction mode: one of 'novice','intermediate' 
[default], 'expert' 


還記得一開始提到交給 OptionParser 建構子的參數 MSG_USAGE 嗎? optparse 套件對 usage訊息也提供了一些支援。在 usage 中使用 "%prog" 關鍵字, OptionParser 會自動將其代換為程式名,即sys.args[0]: 

usage = "usage: %prog [options] arg1 arg2" 


如果程式名為 "myprog",則出現在 help 訊息中的 usage 就會是: 

usage = "usage: myprog [options] arg1 arg2" 


如果OptionParser 建構子沒有收到任何參數,則會自動產生一個 usage訊息: 

"usage: %prog [options]" 


前提是程式沒有 positional argument。甭擔心 option 在 help 訊息中排列的方式,OptionParser 會搞定一切,如同前面程式所示。 

替 option 分門別類: 

如果能夠在 help 訊息中,將性質相近的 option 放在一起,與其它 option明顯區別開來,相信使用者在閱讀時,就能夠很快地查到所要的資訊了。 optparse 套件提供了將 option 以 group分開的機制: 

group = OptionGroup(parser, "DangerousOptions", 
"Caution: use these options at your own risk." 
"It is believed that some of them bite.") 
group.add_option("-g", action="store_true", help="Groupoption.") 
parser.add_option_group(group) 


首先產生一個 OptionGroup 物件,將 OptionParser 和 help 訊息當做參數交給建構子,然後呼叫OptionGroup.add_option() 加入 option,最後再呼叫OptionParser.add_option_group() 加入此 group。如此 help 訊息中的 option 就會按group 顯示了! 

usage: [options] arg1 arg2 

options: 
-h, --help show this help message and exit 
-v, --verbose make lots of noise [default] 
-q, --quiet be vewwy quiet (I'm huntingwabbits) 
-fFILE, --file=FILE write output to FILE 
-mMODE, --mode=MODE interaction mode: one of 'novice','intermediate' 
[default], 'expert' 

Dangerous Options: 
Caution: use of these options is at your own risk. It is believedthat 
some of them bite. 
-g Group option. 


顯示程式版本: 

無論是 GUI 或是 CUI 程式,使用者都會關心目前的程式版本資訊。 optparse套件也提供了版本資訊的支援: 

parser = OptionParser(usage="%prog [-f] [-q]", version="%prog1.0") 


在 OptionParser 建構時指定 version 參數,並將提供版本訊息(先前提到的 "%prot"關鍵字亦可用在此處)。當使用者下達的命令中帶有參數 "---version" (只有 "-v"不行)時,程式會顯示版本資訊: 

$/usr/bin/foo --version 
foo 1.0 


指定讀入 option argument 的個數: 

add_option() 有一個參數 nargs,用以指定該 option 會從命令列上讀入幾個 optionargument。舉例來說,如果 add_option(..., narg = 3,...): 

$myprog --file w x y z 


則 opts.file 將會是一個 tuple,內容為 ('w', 'z', 'y')。如果 option argument個數不足,程式會回應錯誤訊息。 

type of an option: 

在加入 option 時,參數 type 代表該 option 儲存 dest 的型態。支援的型態有 string, int,long, choice, float 和 complex。若要加入其它型態,請參考 Python Library Reference6.20.5 小節,"Extending optparse"。 
對於 string 型態的 option, option argument 會被直接將結果存入dest。 

對於 int, long, float 和 complex 型態, option argument會被轉換成相對應的型別;如果轉換的過程失敗,例如原本預期收到一個int,卻收到一個字串,程式會結束並列印錯誤訊息。 

對於 choice 型態, 在呼叫 OptionParser.add_option() 要指定一個由字串所組成的 tuple 或list 給 choice 參數,接著 OptionParser.check_choice() 會比對傳入的 optionargument 是否和 choice tuple 或 choice list 相同,若不相同則會丟出OptionValueError。 

action of an option: 

在加入 option 時,參數 action 代表對 option argument 所要進行的動作。參數action 有下列幾種: 
<ul> 
<li>store : 預設的 action,將option argument 存到指定的dest。</li> 
<li>store_const : 將 dest的值設為一個給定的常數。</li> 

make_option("-q", "--quiet", 
action="store_const", const=0,dest="verbose"), 
make_option("-v", "--verbose", 
action="store_const", const=1,dest="verbose"), 
make_option("--noisy", 
action="store_const", const=2,dest="verbose"), 


當 "--noisy" 出現時, opts.verbose 的值將會被設定成2。<br> 
</li> 
<li>store_true : 將 dest 的值設定為True。<br></li> 
<li>store_false : 將 dest 的值設定為False。<br></li> 
<li>append : 將 option argument 增加到dest 中,而 dest 的型態將會是 list。使用 append action 時,命令列中可以重覆出現option 和 option argument: 

$myprog -f 1 -f 2 -f 3 


則 opts.optargs 將會是 ['1', '2', '3']。如果是 store action,那麼opts.optargs 將只會是 3,因為每指定一次 option, dest的值就一直被更新。 

若呼叫 add_option() 時參數 nargs 被設定,而 action = append時,程式可以接受下列命令列參數: 

parser.add_option(dest = "optargs", 
action = "append", 
nargs = 3) 
... 
print opts.optargs 

----------------------------- 

$myprog -f 1 2 3 -f 4 5 6 -f 7 8 9 
[('1', '2', '3'), ('4', '5', '6'), ('7', '8','9')] 


看出其中差異了嗎? nargs 會將 option argument 包裝成 tuple,而 append 參數會將包裝好的tuple 再"附加"到原有的 list中。</li> 
<li>count : 將 dest 的值加 1。 dest的值會被初始會 0,該 option 每出現一次, dest 的值就增加1。<br></li> 
<li>callback : 請參考 Python LibraryReference6.20.4。<br></li> 
<li>help : 列印 help訊息。<br></li> 
<li>version :列印程式版本。<br></li> 
</ul> 

錯誤處置: 
如果 option 預期會收到一個 int,而使用者傳入的是 string參數時,會發生什麼事? 

optParser.add_option("-n", 
dest = "theNumber", 
type = "int") 


若使用者輸入的命令是: 

$ /usr/bin/foo -n abc 


程式會發出錯誤訊息,並告知使用者輸入的參數有誤,並且以非零的回傳值結束: 

usage: foo[ -n<theNumber>] 

foo: error: option -n: invalid integer value:'abc' 


OptionParser 的一些操作方法: 

在加入 option 或解讀完參數之後,可以透過 OptionParser 的一些方法來得到一些資訊(以下的 opt_str 就是"-f", "--file" 這些在增加 option 時所用到的參數): 

<UL> 
<LI>has_option(opt_str) : 檢查OptionParser 中是否有某個option。</LI> 
<LI>get_option(opt_str) : 取得OptionParser 中的某個option。</LI> 
<LI>remove_option(opt_str) : 刪除OptionParser 中的某個option。</LI> 
</UL> 

當 option 發生碰撞(重覆)時: 

option 以下列的方式加入時: 

parser.add_option("-n", "--dry-run", ...) 
... 
parser.add_option("-n", "--noisy", ...) 


就稱為"碰撞"。當 option 碰撞時, optparse 會丟出OptionConflictError。程式設計師應該在設計期就解決掉這個問題,也就是說,不應該使用 try - except來捕捉這個錯誤 - 畢竟這在設計期就可以被處理掉的。 

當 OptionParser 的被繼承時,一些標準的 option 就很有可能被子類別覆蓋掉。這種情況下,可以設定OptionParse 處置碰撞的方式: 

parser.set_conflict_handler("resolve") 
or 
parser = OptionParser(...,conflict_handler="resolve") 


都可以讓後來加入的 option 覆蓋掉原有的 option。預設的 conflict_handler 值為"error",也就是直接丟出 OptionConflictError。所謂覆蓋,也不是直接移除掉原有的option,而是避開後來加入的 option: 

parser =OptionParser(conflict_handler="resolve") 

parser.add_option("-n", "--dry-run", ..., help="original dry-runoption") 
... 
parser.add_option("-n", "--noisy", ..., help="benoisy") 


在 help 訊息中,就會看到: 

options: 
--dry-run original dry-run option 
... 
-n, --noisy be noisy 


第一個 option

原创粉丝点击