설명과 코드는 따르기가 어렵지만 주 및 하위 해석자가 dest
을 공유 할 때 기본값을 처리하는 방법에 문제가 있다고 결론을 냈습니다. , foo
는 구문 분석 문자열로 설정되어 나는이 개 실행
처음에
1315:~/mypy$ python3.5 stack41431025.py cmd1 --foo 1
Namespace(cmd='cmd1', foo='1')
1316:~/mypy$ python3.5 stack41431025.py --foo 1 cmd1
Namespace(cmd='cmd1', foo='sub')
얻을
import argparse
class Parsing(object):
def __init__(self):
self.parser = argparse.ArgumentParser(prog='prog',
description='some description')
self.subparser = self.parser.add_subparsers(dest='cmd', title='Cmds', help='help description')
self.make_subparsers(['cmd1','cmd2'])
def make_subparsers(self, parsers):
for each in parsers:
subp = self.subparser.add_parser(each)
self.optional(subp, default='sub')
self.optional(self.parser, default='main')
def optional(self, parser, default=None):
parser.add_argument('--foo', default=default)
args = Parsing().parser.parse_args()
print(args)
:
나는 조금 내가 테스트 실행을 만들 수있는 코드를 응축
cmd1
subparser.
두 번째 경우 foo
은 하위 파서가 설정 한 기본값을 가져옵니다. 주 파서는 --foo
을 파싱했지만 그 값은 서브 파서가 작성한 것 이상이었습니다.
버그/문제에서 이에 대한 논의가있었습니다. http://bugs.python.org/issue9351은 처리를 변경하여 하위 파서 기본값이 주 파서 값보다 우선 순위가 높습니다. 나는 그 패치에 문제가 있다고 생각하지만, 2 년 동안 유효했다.
다른 컨트롤이있는 경우 dest
을 지정합니다.
def make_subparsers(self, parsers):
for each in parsers:
subp = self.subparser.add_parser(each)
self.optional(subp, default='sub')
self.optional(self.parser, default='main', dest='main_foo')
def optional(self, parser, default=None, dest=None):
parser.add_argument('--foo', default=default, dest=dest)
1325:~/mypy$ python3.5 stack41431025.py --foo 1 cmd1
Namespace(cmd='cmd1', foo='sub', main_foo='1')
1325:~/mypy$ python3.5 stack41431025.py cmd1
Namespace(cmd='cmd1', foo='sub', main_foo='main')
1325:~/mypy$ python3.5 stack41431025.py --foo 1 cmd1 --foo 2
Namespace(cmd='cmd1', foo='2', main_foo='1')
====================
내가 인수의 가능한 조합을 스케치하려고합니다
(이전 대답)
python prog.py foo [--mainopt bar] cmd1 sfoo [--subopt baz]
:
parser = argparse.ArgumentParser()
parser.add_argument('mainpos', help='positional for main')
parser.add_argument('--mainopt', help='optional defined for main')
sp = parser.add_subparser(dest='cmd')
p1 = sp.add_parser('cmd1')
p1.add_argument('subpos', help='postional for sub')
p1.add_argument('--subopt', help='optional defined for sub')
복합 usage
과 같을 것이다
해당 positionals
은 올바른 순서로 지정해야합니다. 서브 파서 cmd
은 실질적으로 main
의 위치입니다.
main에 대해 정의 된 선택적 요소는 하위 구문 이름 앞에 있어야합니다. 서브 파서에 대해 정의 된 옵션은 이후에 발생해야합니다. flag
또는 dest
을 가질 수 있지만 별도로 정의해야합니다. 그리고 그들이 동일한 dest
을 가지고 있다면, 값들, 특히 디폴트들에 충돌이있을 수 있습니다.
parser.parse_args()
은 인수를 입력 문자열과 일치시키기 시작합니다. 그것은 --mainopt
이 선택적 인수를 구문 분석하는 것으로 보는 경우. 그렇지 않으면 그것은 2 개의 postionals을 기대합니다. 두 번째는 서브 파서 이름 중 하나 여야합니다.
하위 파서 이름을 가져 오면 나머지 문자열을 해당 하위 파서에 전달합니다. 하위 파서는 나머지를 처리하고 주 네임 스페이스에 값을 저장합니다. 서브 파서가하는 첫 번째 작업은 기본값으로 설정됩니다. 이 동작이 주 파서에 의해 설정된 값을 덮어 쓰는지 아닌지는 namespace
이 둘 사이에서 어떻게 전달되는지에 달려 있습니다.
================
파싱 명령 행에서 인수의 순서에 의해 구동된다. 플래그가 지정된 인수를 임의의 순서로 허용합니다. 그러나 구문 분석이 하위 파서로 전달되면 주 파서는 구문 분석을 수행하지 않습니다. 단지 몇 가지 정리 작업을 수행합니다.
그러나 parse_known_args
을 사용하면 구문 분석기가 처리하지 않은 문자열을 수집하고 구문 분석을 한 번 더 수행 할 수 있습니다.
parser1 = argparse.ArgumentParser()
parser1.add_argument('--foo')
sp = parser1.add_subparsers(dest='cmd')
sp1 = sp.add_parser('cmd1')
args, extra = parser1.parse_known_args()
parser2 = argparse.ArgumentParser()
parser2.add_argument('--foo')
if extra:
args = parser2.parse_args(extra)
print(args)
실행
1815:~/mypy$ python stack41431025.py --foo 1 cmd1
Namespace(cmd='cmd1', foo='1')
1815:~/mypy$ python stack41431025.py cmd1 --foo 2
Namespace(foo='2')
1815:~/mypy$ python stack41431025.py --foo 1 cmd1 --foo 3
Namespace(foo='3')
는 좀 더 복잡한 아무것도에서이 아이디어를 테스트하지, 그래서 내가 생각하지 않은 몇 가지 상호 작용이있을 수 있습니다. 그러나 이것은 어디에서나 발생할 수있는 논쟁의 여지가있는 가장 가까운 곳이며, default
문제와 충돌하지 않아야합니다.
고맙습니다. Hpaulj, 내 코드에 맞게 테스트 해 보겠습니다. – Flippym
올바르게 이해했다면,'argparse'는 전역 인수를 지원하지 않습니다. 각각의 서브 파서에서'dest'로 제어해야합니다. ? – Flippym
'parse_known_args'와 두 번째 파싱 실행을 사용하여 예제를 추가했습니다. – hpaulj