2011-01-22 137 views
17

如果我的參數'-a', '-b', '-c', '-d',與add_mutually_exclusive_group()函數我的程序將不得不使用其中的一個。有沒有辦法將這個結合起來,以便程序只接受'-a 999 -b 999''-c 999 -d 999'argparse(python)是否支持相互排斥的參數組?

編輯:添加一個簡單的程序更加清晰:

>>> parser = argparse.ArgumentParser() 
>>> group = parser.add_mutually_exclusive_group() 
>>> group.add_argument('-a') 
>>> group.add_argument('-b') 
>>> group.add_argument('-c') 
>>> group.add_argument('-d') 

那麼只有./app.py -a | ./app.py -b | ./app.py -c | ./app.py -d可以被調用。是否有可能擁有argparse組排除組,以便只調用./app.py -a .. -b .. | ./app.py -c .. -d ..

回答

6

編輯:沒關係。因爲​​使得在調用group.add_argument時必須創建選項的可怕選擇。那不會是我的設計選擇。如果此功能是絕望的,你可以嘗試用ConflictsOptionParser做:

# exclusivegroups.py 
import conflictsparse 

parser = conflictsparse.ConflictsOptionParser() 
a_opt = parser.add_option('-a') 
b_opt = parser.add_option('-b') 
c_opt = parser.add_option('-c') 
d_opt = parser.add_option('-d') 

import itertools 
compatible_opts1 = (a_opt, b_opt) 
compatible_opts2 = (c_opt, d_opt) 
exclusives = itertools.product(compatible_opts1, compatible_opts2) 
for exclusive_grp in exclusives: 
    parser.register_conflict(exclusive_grp) 


opts, args = parser.parse_args() 
print "opts: ", opts 
print "args: ", args 

因此,當我們調用它,我們可以看到,我們得到想要的效果。

$ python exclusivegroups.py -a 1 -b 2 
opts: {'a': '1', 'c': None, 'b': '2', 'd': None} 
args: [] 
$ python exclusivegroups.py -c 3 -d 2 
opts: {'a': None, 'c': '3', 'b': None, 'd': '2'} 
args: [] 
$ python exclusivegroups.py -a 1 -b 2 -c 3 
Usage: exclusivegroups.py [options] 

exclusivegroups.py: error: -b, -c are incompatible options. 

警告消息不會通知您,無論'-a''-b''-c'不兼容,但是一個更合適的錯誤信息,可以製作。下面的老的,錯誤的答案。

OLDER編輯:[編輯這是錯誤的,但不會是隻是一個完美的世界,如果​​曾這樣?]我以前的答案其實是不正確的,你應該能夠​​做到這一點通過爲每個互斥選項指定一個組。我們甚至可以使用itertools來概括過程。並且做它,因此我們不必明確地輸出所有組合:

import itertools 
compatible_opts1 = ('-a', '-b') 
compatible_opts2 = ('-c', '-d') 
exclusives = itertools.product(compatible_opts1, compatible_opts2) 
for exclusive_grp in exclusives: 
    group = parser.add_mutually_exclusive_group() 
    group.add_argument(exclusive_grp[0]) 
    group.add_argument(exclusive_grp[1]) 
+1

http://bugs.python.org/issue10984有一個修補程序,可讓您將參數放入多個互斥組中。這是一個簡單的改變。使用重疊組生成有意義的用法更爲重要。 – hpaulj 2013-08-09 05:02:33

5

只是自己偶然發現了這個問題。從我閱讀argparse文檔看來,在argparse中似乎沒有一種簡單的方法來實現這一點。我考慮過使用parse_known_args,但是很快就等於寫了一個特殊用途的argparse版本;-)

也許是一個錯誤報告。同時,如果你願意讓你的用戶做一些額外的輸入,你可以用子組僞造它(例如git和svn的參數如何工作),例如

subparsers = parser.add_subparsers() 
    p_ab = subparsers.add_parser('ab') 
    p_ab.add_argument(...) 

    p_cd = subparsers.add_parser('cd') 
    p_cd.add_argument(...) 

並不理想,但至少它可以讓你從argparse沒有太多的醜陋兩輪牛車的好。我最終取消了交換機,只是使用具有所需子參數的子分析器操作。