2013-01-18 2 views
5

argparse (또는 다른 것을 사용합니까?) 각 위치 인수에 선택적 인수가 기본값으로 갖게하고 싶습니다.각 위치 지정 인수에 대한 선택적 인수

인수는 그렇게 될 것이다 :

script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5 

와 나는 위치 인수 목록 및 채워 기본값과 선택적 인수 의 목록과 같은 사용 가능한 것을,이 점을 구문 분석합니다. 예 : 옵션의 기본은 위의 예에서 0 인 경우 :

positional = [arg1, arg2, arg3, arg4, arg5] 
optional = [0, 1, 2, 0, 0] 

, parser.add_argument('-o', action='append') 내가 위치 인수를 잃고 있기 때문에, 각 선택적 인수가 연관되어 원하는 없습니다.

+0

얼마나 많은 위치 인수가 있습니까? – mgilson

+0

아니요. 몇 개에 관계없이 인수를 반복하고 싶습니다. – bkanuka

답변

3

는 여기에 내가 시작하는 적절한 장소가 될 수있는 것을 함께 넣어 간단한 해킹 :

import argparse 

class PositionalAction(argparse.Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     lst = getattr(namespace,self.dest) 
     lst.append(values) 
     parser.last_positional_values = lst 
     all_positional = getattr(namespace,'all_positional',[]) 
     all_positional.append(lst) 
     namespace.all_positional = all_positional 

class AssociateAction(argparse.Action): 
    def __call__(self,parser,namespace,values,option_string=None): 
     try: 
      parser.last_positional_values.append(values) 
     except AttributeError: 
      pass 

parser = argparse.ArgumentParser() 
parser.add_argument('-o',action=AssociateAction,dest=argparse.SUPPRESS) 
junk,unknown = parser.parse_known_args() 

for i,_ in enumerate(unknown): 
    parser.add_argument('arg%d'%i,action=PositionalAction,default=[]) 

print parser.parse_args() 

그리고 여기 행동에 :

temp $ python test1.py foo -o 1 bar -o 2 baz qux -o 4 
Namespace(all_positional=[['foo', '1'], ['bar', '2'], ['baz'], ['qux', '4']], arg0=['foo', '1'], arg1=['bar', '2'], arg2=['baz'], arg3=['qux', '4']) 

이 문제는 몇 가지 문제가 있습니다. 첫째, 임의의 수의 위치 인수를 받아들이려고합니다. argparse는 그것을 좋아하지 않습니다. argparse는 무엇을 기대해야하는지 알기를 원합니다. 해결 방법은 구문 분석기를 작성하고 명령 줄을 구문 분석하는 것이지만 알려진 인수 만 구문 분석하도록 알리는 것입니다 (이 경우 위치가 아닌 -o 인수는 모두 자동으로 구문 분석되지만 "위치"인수는 구문 분석되지 않습니다). . parse_known_args(namespace_of_parsed_stuff, uknown_args) 형식의 튜플을 반환하므로 완벽합니다. 이제 우리는 알려지지 않은 인수를 알았습니다. parse_args를 행복하게 만들기 위해 각 구문 분석기에 위치 인수를 추가하기 만하면됩니다.

이제 실제로 수행하는 사용자 지정 동작은 무엇입니까? 두 번째 단계에서 위치 인수가 발견되면 기본값 (목록)을 가져 와서 그 목록에 값을 추가합니다 (이후에서는이를 "값"목록이라고합니다). 그런 다음 파서을 "값"목록에 대한 참조로 수정합니다. 또한 네임 스페이스에서 "all_positional"목록을 얻습니다. 그 속성이 없다면 빈리스트 만 얻는다. "value"목록을 "all_positional"목록에 추가하고 이름 공간에 다시 넣습니다.

이제 -o 플래그를 누르면 "값"목록을 가져 오기 위해 파서가 표시되고 추가 값이 목록에 추가됩니다. 파서를 전혀 건드리지 않고 똑같은 일을 할 수 있습니다 ... (우리는 namespace.all_positional[-1]을 볼 수 있습니다 - parser.last_positional_values과 같은 목록입니다).

+0

당신이 만든이 마술은 내가 원하는 것을 (또는 충분히 가까이서)하는 것처럼 보이지만, 당신이 한 일을 완전히 이해하는 데는 어느 정도 시간이 걸릴 것입니다. 어쨌든, 고마워! – bkanuka

+0

더 잘 이해할 수 있도록하기 위해 앞으로 진행될 일에 대해 몇 가지 의견을 추가하겠습니다. – mgilson

+0

오해는 확실히 명확성이 부족한 것보다 내 전문 지식 부족과 관련이 있습니다. – bkanuka

-1

작은 조금 복잡 경우 사용 optparse, 그것은 강력 :

op = optparse.OptionParser(usage=usage) 

op.add_option('-c','--cmd',dest='cmd',help="""Command to run. Mutually exclusive with -s. You can use string ${ADDR} to have it replaced with specified host address in the command. """) 

op.add_option('-s','--script',dest='script',help="""Script file to run remotely. Mutually exclusive with -c. A script can have its own arguments; specify the whole command in doublequotes, like "script -arg arg".""") 

op.add_option('-l','--replicate-owner',dest='replicateowner',action="store_true",help="""Replicate (symbolic) owner and (symbolic) group of the file on the remote host, if possible. If remote account with username the same as local account does not exist on remote host, this will silently fail.""") 

# parse cmdline options 
(opts, args) = op.parse_args() 

OPTS는 인수 및 인수 당신에게 위치 인수를 가져옵니다이라는 가져옵니다.

값을 취하거나 위치를 참 또는 거짓으로 설정하고 더 많은 IIRC를 설정할 수 있습니다.

+2

이것은 특정 질문에 대답하지 않습니다. 포스터는 일반적으로 {opt, arg} 구문을 사용하는 방법을 알고 있습니다. – chepner

0

간단히 sys.argv를 단계별로 실행하는 방법은 무엇입니까? 당신은 argparse가 제공하는 추가 기능을 필요로하지 않는 것 같습니다. 예를 들면 다음과 같습니다.

argv='script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5'.split() 
pos=[] 
opt=[] 
i=1 
while i<len(argv): 
    a=argv[i] 
    if a[:2]!='-o': 
     pos.append(a) 
     opt.append(0) 
    else: 
     i += 1 
     opt[-1]=argv[i] 
    i += 1 
관련 문제