1. 程式人生 > >python 命令列引數解析 argparse簡單分析

python 命令列引數解析 argparse簡單分析

在python 2.7 後,不推薦使用 optparse, 而推薦使用 argparse.

其它的不多說,簡單的分析下我遇到的問題:我是想用 argparse 來解析不定長的命令列引數

例如:

import argparse
import sys

parser = argparse.ArgumentParser(description='test parsing arguments')

parser.add_argument('pos1', nargs='*')
parser.add_argument('pos2')
parser.add_argument('-o1')
parser.add_argument('-o2')
parser.add_argument('pos3', nargs='*')

print sys.argv
# arg = parser.parse_args(sys.argv[1:])
arg = parser.parse_known_args(sys.argv[1:])
print arg

# print parser.print_help()

假設將上面的程式碼儲存在 test.py 檔案中,在命令列中做如下測試:

input:   python test.py a b c -o1 d e -o2 f g h

output:

['test.py', 'a', 'b', 'c', '-o1', 'd', 'e', '-o2', 'f', 'g', 'h']
(Namespace(o1='d', o2='f', pos1=['a', 'b'], pos2='c', pos3=[]), ['e', 'g', 'h'])

input: python test.py a  -o1 b c  -o2 d e f g h
output:

['test.py', 'a', '-o1', 'b', 'c', '-o2', 'd', 'e', 'f', 'g', 'h']
(Namespace(o1='b', o2='d', pos1=[], pos2='a', pos3=[]), ['c', 'e', 'f', 'g', 'h'])

input: python test.py -o1 a b c  -o2 d e f g h

output:

['test.py', '-o1', 'a', 'b', 'c', '-o2', 'd', 'e', 'f', 'g', 'h']
(Namespace(o1='a', o2='d', pos1=['b'], pos2='c', pos3=[]), ['e', 'f', 'g', 'h'])

input: python test.py -o1 a -o2 b c d e f g h

output:

['test.py', '-o1', 'a', '-o2', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
(Namespace(o1='a', o2='b', pos1=['c', 'd', 'e', 'f', 'g'], pos2='h', pos3=[]), [])

做如上四組測試,傳入的引數都一樣(唯一不一樣的就是位置), 但是得到了不同的結果。

究其原因,這就是 argparse 模組的實現原理。 採用了正則匹配的方式 來解析引數(正則的說法屬於個人理解,沒有關注原始碼,如果有誤,望更正)

在 add_argument 新增引數規則的時候,我們把帶 '-' 的叫做選項引數,不帶 '-' 的叫做位置引數。 下面我們以位置引數為例

在上面的程式碼中 通過 add_argument 添加了 pos1,pos2,pos3 三個位置引數,他們構成的 正則表示式為 A*AA*,其中A*代表匹配0個或多個值。

在測試例子1中的引數列表中,首先遇到位置引數 a b c ,這正好與 A*AA*的模式匹配,即 pos1=[a,b] pos2=c, pos3=[],因為A*AA*是貪婪匹配模式,即儘可能多的得到值,所以pos1=[a,b]而pos3=[]

在測試例子4中的引數列表中,A*AA* 匹配到引數列表中的 c d e f g h, 在貪婪匹配模式下,即可得到 pos1=[c,d,e,f,g], pos2=h, pos3=[]

通過分析上面兩個例子,我們只需要記住 argparse 解析引數是根據 add_argument 新增的規則來進行模式匹配。就可以較好的理解解析的結果了!