2011-01-22 39 views
17

私が引数'-a', '-b', '-c', '-d'を持っていて、add_mutually_exclusive_group()関数を使っているなら、私のプログラムはそれらのうちのどれか1つを使わなければなりません。それを組み合わせる方法はありますか?そのため、プログラムは'-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

EDIT:決して気にしないでください。​​は、group.add_argumentを呼び出すときにオプションを作成するという恐ろしい選択をするためです。それは私のデザインの選択肢ではありません。したがって

# 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 

を、我々はそれを呼び出すとき、我々は所望の効果を得る見ることができます:あなたはこの機能のために必死にしている場合は、ConflictsOptionParserでそれをやってみることができます。

$ 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 EDIT:[​​がこのように働いていた場合、それだけで完璧な世界ではないでしょうが、この編集は、間違っている?]、あなたは​​でこれを行うことができるはず私の前の回答は、実際には間違っていました相互に排他的なオプションごとに1つのグループを指定します。プロセスを一般化するために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

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からの利益を与えます。私はスイッチを使い果たし、必要なサブ引数を持つサブパーザ操作を使用するだけでした。

関連する問題