2017-10-10 15 views
0

파이썬 2.7을 사용하고 있으며 argparse를 사용하여 동작을 수행하려고합니다. 일반적으로 Python 2.7에서 argparse의 서브 파서를 옵션으로 사용하는 방법을 찾지 못하는 것으로 보입니다. 내 문제를 설명하기가 어려워서 프로그램에서 필요한 것을 설명 할 것입니다. 추가 인수는 특정 작업을 실행합니다 (각 명령은 그 자체가 추가 인수의가) 주어진 명령으로 프로그램을 시작Python 2.7에서 Argparse 모듈을 사용하여 기본 서브 파서를 설정하는 방법

  1. :

    이 프로그램은 작업의 2 가지 모드가 있습니다.

  2. 명령을 사용하지 않고 프로그램을 시작하면 셸 같은 프로그램이 시작됩니다.이 프로그램은 인수 행을 취할 수 있으며 지정된 행을 인수로 사용하여 프로그램이 호출 된 것처럼 처리합니다. 예를 들어 내 프로그램 'CMD1'와 'CMD2'명령을 지원하는 경우

그래서, 난 그렇게처럼 사용할 수 있습니다

  • python program.py cmd1 additional_args1
  • python program.py cmd2 additional_args2

또는 쉘을 모드 :

  • quit
  • 또한

cmd1 additional_args1

  • cmd2 additional_args2
    • , 나는 또한 내 프로그램은 모든 명령에 영향을 것이다 옵션 글로벌 인수를 할 수 있어야합니다. 내가 지금처럼 argparse 사용하고 있는데 그 내용은

      (이것은 순수한 예입니다) :

      parser = argparse.ArgumentParser(description="{} - Version {}".format(PROGRAM_NAME, PROGRAM_VERSION)) 
      
      parser.add_argument("-i", "--info", help="Display more information") 
      
      subparsers = parser.add_subparsers() 
      
      parserCmd1 = subparsers.add_parser("cmd1", help="First Command") 
      parserCmd1.set_defaults(func=cmd1) 
      
      parserCmd2 = subparsers.add_parser("cmd2", help="Second Command") 
      parserCmd2.add_argument("-o", "--output", help="Redirect Output") 
      parserCmd2.set_defaults(func=cmd2) 
      

      그래서 호출 할 수 있습니다 (추가 인수에) CMD1 또는 CMD2 (또는 -o 플래그없이). 그리고 둘 다 플래그 -i를 추가하여 호출 된 명령의 더 많은 정보를 표시 할 수 있습니다.

      • 내가 파이썬을 사용할 수 없습니다

        내 문제는 내가 인수로 CMD1 또는 CMD2을 제공하기 때문에 나는

        제한 (때문에 필수 subparsers를 사용), 쉘 모드를 활성화 할 수 있다는 것입니다 3 (쉽게 수행 할 수 있음을 알고 있습니다)

      • 글로벌 선택적 인수 때문에 arg 구문 분석을 건너 뛰는 인수가 없는지 확인할 수 없습니다. 내가 argparse과 파이썬 2.7과 행동의이 종류를 달성 할 수있는 방법 그래서 모든

      에서 어떤 명령을 제공하지 않는 경우

    • 내가 쉘을 호출하는 새로운 명령을 추가하지 않으
    • , 그것은해야합니다?

  • +0

    그냥 빨리 메모 - subparsers는 선택 사항이라는 사실은 버그입니다. 그들은 (예전 위치에서와 같이) 요구되었지만, 몇 년 전과 무관 한 변화에서, 서브 파서들은 균열을 빠져 나갔다. 이 점에서 Py2와 Py3의 차이점을 왜 생각하는지 이해하기 위해 질문을 자세히 조사해야합니다. – hpaulj

    답변

    1

    또 다른 아이디어는 2 단계 구문 분석을 사용하는 것입니다. 하나는 '전역'을 처리하고 처리 할 수없는 문자열을 반환합니다. 그런 다음 조건에 따라 하위 분석기로 추가 기능을 처리하십시오.

    import argparse 
    
    def cmd1(args): 
        print('cmd1', args) 
    def cmd2(args): 
        print('cmd2', args) 
    
    parser1 = argparse.ArgumentParser() 
    
    parser1.add_argument("-i", "--info", help="Display more information") 
    
    parser2 = argparse.ArgumentParser() 
    subparsers = parser2.add_subparsers(dest='cmd') 
    
    parserCmd1 = subparsers.add_parser("cmd1", help="First Command") 
    parserCmd1.set_defaults(func=cmd1) 
    
    parserCmd2 = subparsers.add_parser("cmd2", help="Second Command") 
    parserCmd2.add_argument("-o", "--output", help="Redirect Output") 
    parserCmd2.set_defaults(func=cmd2) 
    
    args, extras = parser1.parse_known_args() 
    if len(extras)>0 and extras[0] in ['cmd1','cmd2']: 
        args = parser2.parse_args(extras, namespace=args) 
        args.func(args) 
    else: 
        print('doing system with', args, extras) 
    

    샘플 실행 :

    0901:~/mypy$ python stack46667843.py -i info 
    ('doing system with', Namespace(info='info'), []) 
    0901:~/mypy$ python stack46667843.py -i info extras for sys 
    ('doing system with', Namespace(info='info'), ['extras', 'for', 'sys']) 
    0901:~/mypy$ python stack46667843.py -i info cmd1 
    ('cmd1', Namespace(cmd='cmd1', func=<function cmd1 at 0xb74b025c>, info='info')) 
    0901:~/mypy$ python stack46667843.py -i info cmd2 -o out 
    ('cmd2', Namespace(cmd='cmd2', func=<function cmd2 at 0xb719ebc4>, info='info', output='out')) 
    0901:~/mypy$ 
    
    +0

    답장을 보내 주셔서 감사 드리며 답변을 제공해 드릴 수있었습니다. 필요합니다. – Yoavhayun

    1

    '선택적'서브 파서 주제에 버그/문제 (링크 포함)가 있습니다. 이것은 최근의 풀 요청을 가지고

    https://bugs.python.org/issue29298

    알 수 있습니다. 스크립트 및

    args = parser.parse_args() 
    print(args) 
    

    결과를 추가로


    내가 '선택'subparsers이 Py2 3 개 버전 모두에 영향을 생각했지만, 그렇지 않은 분명히

    1008:~/mypy$ python3 stack46667843.py 
    Namespace(info=None) 
    1009:~/mypy$ python2 stack46667843.py 
    usage: stack46667843.py [-h] [-i INFO] {cmd1,cmd2} ... 
    stack46667843.py: error: too few arguments 
    1009:~/mypy$ python2 stack46667843.py cmd1 
    Namespace(func=<function cmd1 at 0xb748825c>, info=None) 
    1011:~/mypy$ python3 stack46667843.py cmd1 
    Namespace(func=<function cmd1 at 0xb7134dac>, info=None) 
    

    있습니다 . 이유를 확인하려면 코드를 살펴 봐야합니다. 두 언어에서


    , subparsers.requiredFalse입니다. 나는 사실

    subparsers.required=True 
    

    로 설정 (그리고 subparsers 정의에 dest 추가)하면 PY3 오류 메시지가

    1031:~/mypy$ python3 stack46667843.py 
    usage: stack46667843.py [-h] [-i INFO] {cmd1,cmd2} ... 
    stack46667843.py: error: the following arguments are required: cmd 
    

    그래서에 차이가있어 얼마나 required 인수에 대한 2 개 버전 테스트. Py3은 required 속성에주의를 기울였습니다. Py2 (분명히)는 positionals 목록이 비어 있는지 여부를 확인하는 이전 방법을 사용합니다.


    parser._parse_known_args 끝 부분에서 필요한 인수가 확인됩니다.

    Python2.7는 action.required 검사를 반복하기 전에

    # if we didn't use all the Positional objects, there were too few 
        # arg strings supplied. 
        if positionals: 
         self.error(_('too few arguments')) 
    

    를 포함한다. 그게 누락 된 cmd을 잡아서 too few arguments이라고 말하는 것입니다.

    그래서 kludge는 argparse.py을 편집하고 해당 블록을 제거하여 Py3 버전의 해당 섹션과 일치하도록합니다.

    +0

    안녕하세요, 응답 해 주셔서 감사합니다. 또한 Python3을 사용할 수없는 동일한 이유로 argparse를 편집 할 수 없습니다. 이 도구는 내가 일하고있는 회사 사람들이 사용하는 도구 일 것입니다. 유일한 보장은 Python 2.7이 설치되어 있다는 것입니다. – Yoavhayun