2014-12-17 5 views
16

저는 python을 처음 사용하고 현재 그 함수를 가지고 놀아 왔습니다. 어플라이언스에 대한 일부 API 호출을 수행하는 스크립트가 있습니다. 기능을 확장하고 스크립트를 호출 할 때 주어진 인수를 기반으로 다른 함수를 호출하고 싶습니다.argparse를 기반으로 한 호출 함수

현재 나는 다음과 같습니다

parser = argparse.ArgumentParser() 
parser.add_argument("--showtop20", help="list top 20 by app", 
        action="store_true") 
parser.add_argument("--listapps", help="list all available apps", 
        action="store_true") 
args = parser.parse_args() 

나는 또한 가지고

def showtop20(): 
    ..... 

내가 함수를 호출 (만이)를 기반으로 어떻게

def listapps(): 
.... 

인수가 주어 졌습니까? 나중에 깨끗하고 깔끔한 주요 실행 파일을 유지에 모듈에 다른 기능을 이동하려는으로 나는

if args.showtop20: 
    #code here 

if args.listapps: 
    #code here 

을 실행하지 않습니다.

+0

당신은'{showtop20 ... 'showtop20을'} 기능에 대한 사전 매핑 인수를 할 수 : 다음은 개념 증명입니다. – jonrsharpe

+1

대신 빈 저장소 함수를 사용하여'store_const'를 사용한 다음 차례대로 모든 함수를 호출하십시오 – njzk2

+0

https://docs.python.org/3/library/argparse.html#sub-commands - 사용 예제를 확인하십시오. 'add_subparsers'와'set_defaults'는 명령과 함수를 연결합니다. – hpaulj

답변

14

하나를 실행하려는 것처럼 보인다 때문에, 단 하나, 주어진 인수에 따라 기능, 당신이 필수을 사용하는 것이 좋습니다 것입니다 위치 지정 인수 ./prog command (선택 인수 (./prog --command1 또는 ./prog --command2) 대신).

그래서, 이런 걸 그것을 수행해야합니다

FUNCTION_MAP = {'top20' : my_top20_func, 
       'listapps' : my_listapps_func } 

parser.add_argument('command', choices=FUNCTION_MAP.keys()) 

args = parser.parse_args() 

func = FUNCTION_MAP[args.command] 
func() 
+1

우선'FUNCTION_MAP'을 먼저 정의하고,'choices = list (FUNCTION_MAP)'를 사용하여 건조하게 유지하는 것이 더 좋습니다. – GP89

+1

우수 아이디어! 코드를 변경했습니다. 나는 그것이 더 명백하다고 생각하기 때문에'list (MAP) '대신에'MAP.keys()'를 사용하는 편이 더 좋겠지 만. –

+0

'choices'는 사전과 잘 동작합니다. 자동으로 키를 사용합니다. – hpaulj

3

당신의 함수는 "간단한 충분"type 매개 변수 https://docs.python.org/2.7/library/argparse.html#type

유형의 adventage을 경우 = 단일 문자열 인수를하고 변환 된 값을 반환하는 모든 호출 수행 할 수 있습니다

에서을 귀하의 예 (전환 된 값이 필요하지 않더라도) :

parser.add_argument("--listapps", help="list all available apps", 
        type=showtop20, 
        action="store") 

이 간단한 스크립트 :

import argparse 

def showtop20(dummy): 
    print "{0}\n".format(dummy) * 5 

parser = argparse.ArgumentParser() 
parser.add_argument("--listapps", help="list all available apps", 
        type=showtop20, 
        action="store") 
args = parser.parse_args() 

가 제공됩니다

# ./test.py --listapps test 
test 
test 
test 
test 
test 
test 
+2

이 코드를 실행 해 보셨습니까? 'store_true'는 인자를 취하지 않으므로'showtop20'가 실행되지 않아야합니다. 기본 '저장소'작업으로 실행되지만, 구문 분석과 실행을 얽히게하는 것은 좋은 생각이라고 생각하지 않습니다. – hpaulj

+1

당신은 rigth 'store'액션이 필요합니다.이 메소드는 일종의 해킹이나 요구 사항에 가장 가까운 것일 수 있습니다. – klashxx

+0

접근 방식의 중요한 차이점은 파서가 여전히 활성화되어있는 동안 함수가 실행된다는 것입니다. 따라서 여러 함수가 순차적으로 호출 될 수 있습니다. 어떤 경우에는 바람직 할 것이고, 어떤 경우에는 디버깅 문제가 발생할 수도 있습니다. – hpaulj

7

이 고양이를 스키닝의 많은 방법이 있습니다. 여기서 (문서화 subparser 예 영감) action='store_const'를 사용하여 하나의 : 공유 dest 함께

p=argparse.ArgumentParser() 
p.add_argument('--cmd1', action='store_const', const=lambda:'cmd1', dest='cmd') 
p.add_argument('--cmd2', action='store_const', const=lambda:'cmd2', dest='cmd') 

args = p.parse_args(['--cmd1']) 
# Out[21]: Namespace(cmd=<function <lambda> at 0x9abf994>) 

p.parse_args(['--cmd2']).cmd() 
# Out[19]: 'cmd2' 
p.parse_args(['--cmd1']).cmd() 
# Out[20]: 'cmd1' 

는, 각 동작은 동일한 네임 스페이스 속성에 그 기능 (const)를 둔다. 이 함수는 args.cmd()에 의해 호출됩니다.

문서화 된 서브 파서의 예와 같이, 이러한 함수는 Namespace의 다른 값을 사용할 수 있도록 작성할 수 있습니다., 문서에 도시 된 바와 같이

p = argparse.ArgumentParser() 
sp = p.add_subparsers(dest='cmdstr') 
sp1 = sp.add_parser('cmd1') 
sp1.set_defaults(cmd=lambda:'cmd1') 
sp2 = sp.add_parser('cmd2') 
sp2.set_defaults(cmd=lambda:'cmd2') 

p.parse_args(['cmd1']).cmd() 
# Out[25]: 'cmd1' 

subparsers는 각 명령에 대해 서로 다른 매개 변수 인수를 정의 할 수 있습니다 :

args = parse_args() 
args.cmd(args) 

비교를 위해, 여기에 해당하는 subparsers 케이스입니다.

물론 이러한 모든 add 인수 또는 구문 분석기 문은 함수와 키가 쌍을 이루는 일부 목록이나 사전에 대한 루프에서 만들 수 있습니다.

또 다른 중요한 고려 사항 - 어떤 종류의 사용과 도움이 필요하십니까? 다른 접근 방식은 매우 다른 도움말 메시지를 생성합니다.

+0

@hpaulk, 나는 이것이 잠시 동안 알고 원래 질문에 특별히 대답하지는 않을 것이지만 각 플래그가 특정 함수를 호출하는 여러 플래그를 전달하는 방법을 찾고있었습니다 (단 하나의 함수가 아닌 " dest "변수). 나는'action = 'append_const'액션을 발견했다. 그 질문에 답을 추가 하시겠습니까? – OozeMeister

+0

예제 예제는 여기 : https://gist.github.com/frenchtoast747/cdbdba055b649f44d0f86bc88d29b6b8 – OozeMeister

1

적어도 사용자가 설명한대로 --showtop20--listapps은 옵션보다 하위 명령처럼 들립니다. 이 경우, 서브 파서를 사용하여 원하는 결과를 얻을 수 있습니다. 함수 이름이 변경/이동하는 경우는 사전을 업데이트 -`:

import argparse 
import sys 

def showtop20(): 
    print('running showtop20') 

def listapps(): 
    print('running listapps') 

parser = argparse.ArgumentParser() 
subparsers = parser.add_subparsers() 

# Create a showtop20 subcommand  
parser_showtop20 = subparsers.add_parser('showtop20', help='list top 20 by app') 
parser_showtop20.set_defaults(func=showtop20) 

# Create a listapps subcommand  
parser_listapps = subparsers.add_parser('listapps', help='list all available apps') 
parser_listapps.set_defaults(func=listapps) 

# Print usage message if no args are supplied. 

# NOTE: Python 2 will error 'too few arguments' if no subcommand is supplied. 
#  No such error occurs in Python 3, which makes it feasible to check 
#  whether a subcommand was provided (displaying a help message if not). 
#  argparse internals vary significantly over the major versions, so it's 
#  much easier to just override the args passed to it. 

if len(sys.argv) <= 1: 
    sys.argv.append('--help') 

options = parser.parse_args() 

# Run the appropriate function (in this case showtop20 or listapps) 
options.func() 

# If you add command-line options, consider passing them to the function, 
# e.g. `options.func(options)` 
관련 문제