2014-12-28 2 views
2

하나의 필수 매개 변수를 사용하는 스크립트를 작성하고 그에 따라 다음 인수의 해석을 변경할 수 있습니다. 대부분의 조합은 잘 진행되고 있지만 문제가있는 조합이 있습니다. 그것은 세 개의 매개 변수, 모든 문자열의 반복 그룹입니다. 반복 그룹에 python argparse 사용

$ python script.py p1 p2_1 p2_2 p2_3 p3_1 p3_2 p3_3

또는 의사 정규식 같은

: 예를 들어

$ python script.py p1 (px_1 px_2 px_3)+

I 입력의 형태를 제어 할 수 없습니다. 명령 행에 비해 stdin을 통해이를 수신하는 옵션이 있습니다. argv에 합류하여 정규 표현식을 사용하여 문자열을 다루는 것이 더 쉽습니다.이 정규 표현식을 사용하면 두 가지를 모두 처리 할 수 ​​있습니다.

argparse와 비슷한 일을하는 몇 가지 다른 답변이 있습니다. 여기 Argparse, handle repeatable set of items 과 :

hpaulj 여기 두 도움이 응답이 Python argparser repeat subparse

후 지금 몇 시간, 나는 어떤 해커없이 argparse이 일을하는 방법을 알아낼 못하고있다. 먼저 첫 번째 매개 변수를 제거한 다음 나머지 매개 변수가 사라질 때까지 반복합니다. 같은 이름 공간 객체에 보관하고 싶습니다. 올바르게 수행하는 방법을 파악할 수있을 것입니다. 위의 답변 중 하나를 기반으로 일부 데모 코드 :

#!/usr/bin/env python 
import argparse 

parser = argparse.ArgumentParser() 
parser.add_argument('param1', type=str) 
param1, remaining = parser.parse_known_args() 

parser = argparse.ArgumentParser() 
parser.add_argument('first', type=str, action='append') 
parser.add_argument('second', type=str, action='append') 
parser.add_argument('third', type=str, action='append') 

repeating_args, remaining = parser.parse_known_args(remaining) 
while remaining: 
    another_set, remaining = parser.parse_known_args(remaining) 
    repeating_args.first.append(another_set.first[0]) 
    repeating_args.second.append(another_set.second[0]) 
    repeating_args.third.append(another_set.third[0]) 

그러나 이것은 단지 나에게 미봉책 느낌과는 방식으로 그 영향을 다른 매개 변수 조합의 코드를 수정하는 저를 강제로. argparse로 이것을 할 수있는 더 좋은 방법이 있습니까? 아니면 내가 이것에 만족하지 않으면, 그냥 argparse를 사용하지 않아야합니까? 불행히도, 그건 내 코드를 많이 재 작성한다는 뜻이야 ...

고마워.

업데이트 된 코드는 :

hpaulj의 응답에 따라, 이것은 내가 사용하고 코드의 압축 및 작업 버전입니다. 파서 구성과 관련하여 상대적으로 일반적이므로 위 코드보다 훨씬 낫습니다. 나는 그것이 도움이되기를 바랍니다.

#!/usr/bin/env python 
import sys 
import argparse 

def parse_args(): 

    # Create the first parser object and get just the first parameter 
    parser = argparse.ArgumentParser('Argument format parser') 
    parser.add_argument('arg_format', type=str, help='The first argument.' + 
         'It tells us what input to expect next.') 
    args_ns, remaining = parser.parse_known_args() 

    # Generate a new parser based on the first parameter 
    parser = formatSpecificParser(args_ns.arg_format) 

    # There will always be at least one set of input (in this case at least) 
    args_ns, remaining = parser.parse_known_args(args=remaining, namespace=args_ns) 

    # Iterate over the remaining input, if any, adding to the namespace 
    while remaining: 
     args_ns, remaining = parser.parse_known_args(args=remaining, 
                namespace=args_ns) 

    return args_ns 

def formatSpecificParser(arg_format): 
    parser = argparse.ArgumentParser("Command line parser for %s" % arg_format) 
    if (arg_format == "format_1"): 
     addArgsFormat1(parser) 
    # elif (...): 
     # other format function calls 
    return parser 

def addArgsFormat1(parser): 
    parser.add_argument('arg1', type=str, action='append', help='helpful text') 
    parser.add_argument('arg2', type=str, action='append', help='helpful text') 
    parser.add_argument('arg3', type=str, action='append', help='helpful text') 

def main(argv): 
    args = parse_args() 
    print (args) 

if __name__ == "__main__": 
    main(sys.argv[1:]) 

명령 줄 출력 : 여기

$ ./example.py format_1 foo bar baz meh meh meh e pluribus unum 
Namespace(arg1=['foo', 'meh', 'e'], arg2=['bar', 'meh', 'pluribus'], arg3=['baz', 'meh', 'unum'], arg_format='format_1') 
+0

논쟁의 출처는 어디일까요? 왜 너는 그들을 통제 할 수 없어? –

+0

변경할 수없는 업스트림 응용 프로그램입니다. –

+0

나는 argparse가 갈 길이라고 생각하지 않습니다 ... 나는 당신의 사건이 무엇인지 잘 모르겠습니다. Argparse는 논쟁을 분석하기위한 것입니다 (놀랍게도). 작동 할 수는 있지만 작업을위한 도구처럼 들리지는 않습니다.데이터를 매개 변수로 사용하여 파이썬 스크립트를 호출 할 수 있다면 메시징 시스템을 사용하여 매개 변수를 어떻게 든 스크립트에 직접 스트리밍 할 수 있습니까? –

답변

0

는 반복되는 부분을 단순화 할 수있는 대략적인 순서입니다 :

In [10]: p=argparse.ArgumentParser() 

In [11]: p.add_argument('p2',nargs=3,action='append') 

In [12]: ns,rest=p.parse_known_args('p21 p22 p23 p31 p32 p33'.split()) 

In [13]: ns 
Out[13]: Namespace(p2=[['p21', 'p22', 'p23']]) 

In [14]: rest 
Out[14]: ['p31', 'p32', 'p33'] 

In [15]: ns,rest=p.parse_known_args(rest,ns) # repeat as needed 

In [16]: ns 
Out[16]: Namespace(p2=[['p21', 'p22', 'p23'], ['p31', 'p32', 'p33']]) 

일반적으로 'APPEND'이후, positionals와 이해가되지 않습니다 그들이 반복 될 수 없다. 그러나 여기에서는 편리하게 하위 목록을 생성합니다. 이전 네임 스페이스를 다음 파싱 단계로 전달하면 이미 파싱 된 값을 기반으로 빌드 할 수 있습니다. 이것은 nargs=3으로 나의 것으로 3 개의 위치 논쟁으로 다만 잘 작동해야한다.

+0

감사합니다. 네임 스페이스를 다시 전달하는 것은 지난 밤에 게시 한 후 나온 것입니다. 아마도 전체 리펙터가 아닌 다른 옵션 중에서 가장 좋은 옵션 일 것입니다. 충분히 깨끗합니다. 필요에 따라 다른 파서로 입력을 반복 할 수 있지만 동일한 네임 스페이스에서 작업하는 것은 실제로 매우 멋진 접근 방식입니다. 사고로 무엇이든 삐걱 거리지 않도록 조심해야합니다. 질문에 업데이트 된 코드를 다른 사람들을위한 참고 자료로 넣을 것입니다. 다시 한 번 감사드립니다! –

관련 문제