2012-04-24 3 views
2

주어진 문자열을 기반으로 사용자 정의 객체 (아래 예제에서 막대)의 인스턴스를 만들어야합니다. 나는 아래의 코드 Bar로하지 변화에게 유형을 실행 경우 : 나는 경우, 그러나argparse와 함께 사용자 정의 유형을 사용할 때 일반적인 인수 오류

usage: Example.py [-h] 
        [-b [{alfa,beta,gamma,delta} [{alfa,beta,gamma,delta} ...]]] 
        foo 
Example.py: error: argument -b/--bar: invalid choice: 'hello' (choose from 'alfa', 'beta', 'gamma', 'delta') 

:

import argparse 

VALID_BAR_NAMES = ['alfa', 'beta', 'gamma', 'delta'] 


class Bar: 

    def __init__(self, name): 
     if not name in VALID_BAR_NAMES: 
      raise RuntimeError('Bar can not be {n}, ' 
           'it must be one of {m}'.format(
            n=name, m=', '.join(VALID_BAR_NAMES))) 
     self.name = name 


if __name__ == '__main__': 
    parser = argparse.ArgumentParser() 

    parser.add_argument('foo', help='Specify the foo!') 

    parser.add_argument('-b', '--bar', nargs='*', 
         choices=VALID_BAR_NAMES, 
         type=str, # SELECTED TYPE 
         help=('Specify one or many valid bar(s)')) 
    parsed_arguments = parser.parse_args() 

을 나는 잘못된 argment 전달이 아니라 좋은 출력 hello-b를 얻을 type=strtype=Bar으로 변경하고 다시 실행하면 다음과 같은 결과가 출력됩니다.

Traceback (most recent call last): 
    File "C:\PyTest\Example.py", line 25, in <module> 
    parsed_arguments = parser.parse_args() 
    File "C:\Python27\lib\argparse.py", line 1688, in parse_args 
    args, argv = self.parse_known_args(args, namespace) 
    File "C:\Python27\lib\argparse.py", line 1720, in parse_known_args 
    namespace, args = self._parse_known_args(args, namespace) 
    File "C:\Python27\lib\argparse.py", line 1926, in _parse_known_args 
    start_index = consume_optional(start_index) 
    File "C:\Python27\lib\argparse.py", line 1866, in consume_optional 
    take_action(action, args, option_string) 
    File "C:\Python27\lib\argparse.py", line 1778, in take_action 
    argument_values = self._get_values(action, argument_strings) 
    File "C:\Python27\lib\argparse.py", line 2218, in _get_values 
    value = [self._get_value(action, v) for v in arg_strings] 
    File "C:\Python27\lib\argparse.py", line 2233, in _get_value 
    result = type_func(arg_string) 
    File "C:\PyTest\Example.py", line 12, in __init__ 
    n=name, m=', '.join(VALID_BAR_NAMES))) 
RuntimeError: Bar can not be hello, it must be one of alfa, beta, gamma, delta 

어느 쪽이 나쁘게 보입니다. 이것이 유형 변환으로 인한 것임을 이해합니다. 에 대한 확인이 완료되었습니다. 이것을 처리하는 가장 좋은 방법은 무엇입니까?

답변

2

당신은 (검증되지 않은) 사용자 지정 작업 만들어야합니다 도움이된다면

class Bar: 
    ... 


class BarAction(argparse.Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     try: #Catch the runtime error if it occures. 
      l=[Bar(v) for v in values] #Create Bars, raise RuntimeError if bad arg passed. 
     except RuntimeError as E: 
      #Optional: Print some other error here. for example: `print E; exit(1)` 
      parser.error() 

     setattr(namespace,self.dest,l) #add the list to the namespace 

... 
parser.add_argument('-b', '--bar', nargs='*', 
        choices=VALID_BAR_NAMES, 
        action=BarAction, # SELECTED TYPE -- The action does all the type conversion instead of the type keyword. 
        help=('Specify one or many valid bar(s)')) 

... 
+2

'parser.error()'외에'raise argparse.ArgumentError (self, "당신의 전용 오류 msg")'도 고려해야한다. 'self'는 현재 인자 객체 인'__call__'에서 당신에게 주어진 객체와 같은'self'입니다. – cfi

1

구문 분석이 완료 될 때까지 인수를 문자열로 유지하십시오. 구문 분석이 끝나면 먼저 도메인 개체로 변환하십시오.

+0

하는이 솔루션은 것 argparse를 호출하고 문자열에서 도메인 객체로 변환 할 때 오류 출력에 사용할 수있는 방법이 있으면 개선되었습니다. 그런 식으로 알고 있다면 별도의 (더 나은) 대답으로 게시하십시오. – Deleted

+0

내 대답보기. – mgilson

0

이 몰라를하지만 난 참고로 argparse.FileType 바라 보았다 :

class Bar: 
    def __call__(self, strting): 
     if not name in VALID_BAR_NAMES: 
      raise argparse.ArgumentError(None,'Bar can not be {n}, ' 
           'it must be one of {m}'.format(
            n=name, m=', '.join(VALID_BAR_NAMES))) 
     self.name = string 

    def __init__(self): 
     pass 

    def __repr__(self): 
     return name 

parser.add_argument('-b', '--bar', nargs='*', 
        choices=VALID_BAR_NAMES, 
        type=Bar(), # SELECTED TYPE 
        help=('Specify one or many valid bar(s)'))