2011-01-22 2 views
17

'-a', '-b', '-c', '-d'이라는 인수가있는 경우 add_mutually_exclusive_group() 함수를 사용하면 프로그램에서 하나만 사용해야합니다. 이를 결합하여 프로그램이 '-a 999 -b 999' 또는 '-c 999 -d 999' 중 하나만 받아 들일 수 있습니까?argparse (파이썬)은 상호 배타적 인 인수 그룹을 지원합니까?

편집 : 더 명확하게하기 위해 간단한 프로그램을 추가 :

>>> 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

수정 : 신경 쓰지 마세요. argparsegroup.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 편집 :[argparse 이런 식으로 일을하면 그냥 완벽한 세계되지 않을 것 있지만이 편집, 잘못?] 당신이 argparse이 작업을 수행 할 수 있어야한다 내 이전의 대답은 실제로 잘못되었습니다 상호 배타적 인 옵션마다 하나의 그룹을 지정합니다. 프로세스를 일반화하기 위해 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의 장점을 제공합니다. 나는 스위치를 없애고 subparser 연산을 필수 서브 테이블과 함께 사용했다.

관련 문제