@Vikas가 제공하는 솔루션은 하위 명령 별 선택적 인수에 대해 실패하지만 접근 방식은 유효합니다. 다음은 개선 된 버전입니다.
import argparse
parser = argparse.ArgumentParser(prog='PROG')
parser.add_argument('--foo', action='store_true', help='foo help')
subparsers = parser.add_subparsers(help='sub-command help', dest='subparser_name')
parser_a = subparsers.add_parser('command_a', help='command_a help')
parser_a.add_argument('bar', type=int, help='bar help')
parser_b = subparsers.add_parser('command_b', help='command_b help')
parser_b.add_argument('--baz', choices='XYZ', help='baz help')
argv = ['--foo', 'command_a', '12', 'command_b', '--baz', 'Z']
while argv:
print(argv)
options, argv = parser.parse_known_args(argv)
print(options)
if not options.subparser_name:
break
이것은 사용하는 parse_known_args
대신 parse_args
. parse_args
현재 서브 파서에 알려지지 않은 인수가 발견되는 즉시 중단됩니다.parse_known_args
, 반환 된 튜플의 두 번째 값으로 반환됩니다. 이 접근 방식에서는 나머지 인수가 파서에 다시 공급됩니다. 따라서 각 명령에 대해 새 네임 스페이스가 생성됩니다.
이 기본 예에서 모든 전역 옵션은 첫 번째 옵션 네임 스페이스에만 추가되며 후속 네임 스페이스에는 추가되지 않습니다.
이 접근 방식은 대부분의 상황에서 잘 작동하지만 세 가지 중요한 제한 사항이 있습니다.
- 같은 다른 하위 명령에 대해 동일한 선택적 인수를 사용할 수 없습니다
myprog.py command_a --foo=bar command_b --foo=bar
.
- 부속 명령 (
nargs='?'
또는 nargs='+'
또는 nargs='*'
) 과 함께 가변 길이 위치 인수를 사용할 수 없습니다 .
- 알려진 인수는 새 명령에서 '중단'없이 구문 분석됩니다. 예
PROG --foo command_b command_a --baz Z 12
를 들어 위의 코드에서는에서 --baz Z
가 아니라에서 소비 command_b
됩니다 command_a
.
이러한 제한은 argparse의 직접적인 제한입니다. 다음은 단일 하위 명령을 사용하는 경우에도 argparse의 제한 사항을 보여주는 간단한 예입니다.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('spam', nargs='?')
subparsers = parser.add_subparsers(help='sub-command help', dest='subparser_name')
parser_a = subparsers.add_parser('command_a', help='command_a help')
parser_a.add_argument('bar', type=int, help='bar help')
parser_b = subparsers.add_parser('command_b', help='command_b help')
options = parser.parse_args('command_a 42'.split())
print(options)
이것은 error: argument subparser_name: invalid choice: '42' (choose from 'command_a', 'command_b')
.
원인은 내부 방법 argparse.ArgParser._parse_known_args()
이 너무 탐욕스럽고 그것이 command_a
선택적인 spam
인수 의 값 이라고 가정하기 때문 입니다 . 특히, 선택적 및 위치 인수를 '분할'할 때 _parse_known_args()
arugment의 이름 (예 : command_a
또는 command_b
)을 보지 않고 인수 목록에서 발생하는 위치 만 확인합니다. 또한 모든 하위 명령이 나머지 인수를 모두 사용한다고 가정합니다. 이 제한은 argparse
또한 다중 명령 하위 구문 분석기의 적절한 구현을 방해합니다. 이는 안타깝게도 적절한 구현을 위해서는 argparse.ArgParser._parse_known_args()
메서드를 완전히 다시 작성해야하며 이는 200 줄 이상의 코드가 필요함을 의미합니다 .
이러한 제한을 감안할 때 하위 명령 대신 단일 객관식 인수로 간단히 되 돌리는 옵션이 될 수 있습니다.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--bar', type=int, help='bar help')
parser.add_argument('commands', nargs='*', metavar='COMMAND',
choices=['command_a', 'command_b'])
options = parser.parse_args('--bar 2 command_a command_b'.split())
print(options)
사용 정보에 다른 명령을 나열하는 것도 가능합니다. 내 대답 https://stackoverflow.com/a/49999185/428542를 참조하십시오.