argparse를 사용하여 목록을 명령 행 인수로 전달하려면 어떻게해야합니까?


443

명령 줄 프로그램에 인수로 목록을 전달하려고합니다. 거기에 argparse옵션으로 목록을 전달하는 옵션은?

parser.add_argument('-l', '--list',
                      type=list, action='store',
                      dest='list',
                      help='<Required> Set flag',
                      required=True)

스크립트는 아래와 같이 불립니다

python test.py -l "265340 268738 270774 270817"

답변:


880

TL; DR

사용자 인터페이스의 작동 방식에 따라 nargs옵션 또는 옵션 'append'설정을 사용하십시오 action.

나르 그

parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567

nargs='+'하나 이상의 인수를 nargs='*'취하고 0 이상을 취합니다.

덧붙이다

parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 -l 2345 -l 3456 -l 4567

함께 append하면 목록을 구축 할 수있는 옵션이 여러 번 제공합니다.

사용하지 마십시오 type=list! - type=list함께 사용하고 싶은 상황은 없을 것 입니다 argparse. 이제까지.


이를 위해 시도 할 수있는 여러 가지 방법과 최종 결과에 대해 자세히 살펴 보겠습니다.

import argparse

parser = argparse.ArgumentParser()

# By default it will fail with multiple arguments.
parser.add_argument('--default')

# Telling the type to be a list will also fail for multiple arguments,
# but give incorrect results for a single argument.
parser.add_argument('--list-type', type=list)

# This will allow you to provide multiple arguments, but you will get
# a list of lists which is not desired.
parser.add_argument('--list-type-nargs', type=list, nargs='+')

# This is the correct way to handle accepting multiple arguments.
# '+' == 1 or more.
# '*' == 0 or more.
# '?' == 0 or 1.
# An int is an explicit number of arguments to accept.
parser.add_argument('--nargs', nargs='+')

# To make the input integers
parser.add_argument('--nargs-int-type', nargs='+', type=int)

# An alternate way to accept multiple inputs, but you must
# provide the flag once per input. Of course, you can use
# type=int here if you want.
parser.add_argument('--append-action', action='append')

# To show the results of the given option to screen.
for _, value in parser.parse_args()._get_kwargs():
    if value is not None:
        print(value)

기대할 수있는 결과는 다음과 같습니다.

$ python arg.py --default 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ python arg.py --list-type 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ # Quotes won't help here... 
$ python arg.py --list-type "1234 2345 3456 4567"
['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7']

$ python arg.py --list-type-nargs 1234 2345 3456 4567
[['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']]

$ python arg.py --nargs 1234 2345 3456 4567
['1234', '2345', '3456', '4567']

$ python arg.py --nargs-int-type 1234 2345 3456 4567
[1234, 2345, 3456, 4567]

$ # Negative numbers are handled perfectly fine out of the box.
$ python arg.py --nargs-int-type -1234 2345 -3456 4567
[-1234, 2345, -3456, 4567]

$ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567
['1234', '2345', '3456', '4567']

테이크 아웃 :

  • 사용 nargs또는action='append'
    • nargs사용자 관점에서 더 간단 할 수 있지만 위치 인수 argparse가 있어야하는 위치와 위치 인수가 무엇인지 알 수 없기 때문에 위치 인수가 있으면 직관적이지 않을 수 있습니다 nargs. 위치 인수가 있으면 action='append'더 나은 선택이 될 수 있습니다.
    • 경우 위의 사실이 아니라 nargs주어진 '*', '+'또는 '?'. 정수 숫자 (예 :)를 제공하면 옵션에 대해 예상되는 값의 수를 정확히 알 수 4있으므로 옵션 nargs과 위치 인수를 혼합하는 데 문제가 없습니다 argparse.
  • 명령 행에 따옴표를 사용하지 마십시오 1
  • type=list목록의 목록을 반환하므로를 사용하지 마십시오
    • 이것은 후드 아래에서 모든 인수의 집계가 아니라 선택한 개별 인수에 대해 개별 인수 를 강제하기 위해 argparse의 값을 사용 하기 때문 입니다.typetype
    • type=intint (또는 무엇이든) 목록을 얻기 위해 (또는 무엇이든) 사용할 수 있습니다

1 : 나는 일반적으로 의미하지 않습니다 .. 목록을 전달하기argparse 위해 따옴표를 사용 하는 것은 당신이 원하는 것이 아닙니다.


3
문자열 목록은 어떻습니까? 그러면 여러 문자열 인수 ( "wassup", "something"및 "else")가 다음과 같은 목록으로 바뀝니다. [[ 'w', 'a', 's', 's', 'u' , 'p'], [ 's', 'o', 'm', 'e', ​​'t', 'h', 'i', 'n', 'g'], [ 'e', ​​' l ','s ','e ']]
rd108

3
@ rd108 나는 당신이 type=list옵션을 사용하고 있다고 확신합니다 . 사용하지 마십시오. 문자열을 목록으로 만들어서 목록 목록으로 만듭니다.
SethMMorton

1
@Dror type매개 변수를 다른 개체로 설정하지 않으면 모든 입력이 문자열로 간주됩니다 . 기본적으로이 메소드는 문자열 목록을 리턴합니다.
SethMMorton

1
--옵션과 위치 인수를 분리 할 수 ​​있습니다. prog --opt1 par1 ... -- posp1 posp2 ...
0andriy

1
argparse가 위치 인수가 무엇인지, nargs에 속하는 것이 무엇인지 알 수 없기 때문에 위치 인수가 있으면 직관적이지 않을 수 있습니다 . --이전 주석의 예와 같이 이것을 알아내는 데 도움이됩니다. IOW 사용자는 --모든 위치 인수를 제공합니다.
0andriy

83

스크립트에서 나중에 구문 분석하는 구분 된 문자열을 전달하는 것을 선호합니다. 그 이유는 다음과 같습니다. 목록은 모든 유형의 수 있습니다 int또는 str, 때로는 사용하여 nargs여러 선택적 인수 및 위치 인수가있는 경우 문제가 I 실행.

parser = ArgumentParser()
parser.add_argument('-l', '--list', help='delimited list input', type=str)
args = parser.parse_args()
my_list = [int(item) for item in args.list.split(',')]

그때,

python test.py -l "265340,268738,270774,270817" [other arguments]

또는,

python test.py -l 265340,268738,270774,270817 [other arguments]

잘 작동합니다. 구분 기호도 공백이 될 수 있지만 질문의 예와 같이 인수 값 주위에 인용 부호를 적용합니다.


57
사후 처리 대신 type인수를 설정할 수 있습니다 . lambda s: [int(time) for item in s.split(',')]args.list
chepner

13
@ chepner, 그렇습니다. 당신은 절대적으로 옳고 그것은 더 pythonic 일 것입니다-작은 오타 int(time)가 있습니다 int(item). 내 예는 내가 일반적으로하는 일의 단순화 된 버전으로 간단한 처리가 아닌 다른 많은 것들을 확인합니다. 그러나 단순히 그 질문에 답하기 위해 당신의 길을 더 우아하게 생각합니다.
dojuba

1
이 답변은 가장 파이썬 같은 것 같습니다
Quetzalcoatl

1
@chepner의 코멘트는 심각한 닌자 기술이다 +1
Briford Wylie

1
lambda items: list(csv.reader([items]))[0]표준과 CSV의 라이브러리에서 주석의 수정 된 버전입니다 @chepner (: 심판 사람이 임의의 CSV 입력에 대한 걱정에 대한 대답 에서 @adamk은 ).
Kevin

19

또한 목록을 미리 알고 있으면 nargs사용할 수도 있습니다 choices.

>>> parser = argparse.ArgumentParser(prog='game.py')
>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors'])
>>> parser.parse_args(['rock'])
Namespace(move='rock')
>>> parser.parse_args(['fire'])
usage: game.py [-h] {rock,paper,scissors}
game.py: error: argument move: invalid choice: 'fire' (choose from 'rock',
'paper', 'scissors')

10

argparse의 add_argument 메소드에서 nargs 매개 변수 사용

nargs = ' '를 add_argument 매개 변수로 사용합니다. 명시 적 인수를 전달하지 않으면 기본값을 선택하는 옵션에 nargs = ' '를 사용했습니다.

예제로 코드 스 니펫 포함 :

예 : temp_args1.py

참고 : 아래 샘플 코드는 python3으로 작성되었습니다. print 문 형식을 변경하면 python2에서 실행할 수 있습니다

#!/usr/local/bin/python3.6

from argparse import ArgumentParser

description = 'testing for passing multiple arguments and to get list of args'
parser = ArgumentParser(description=description)
parser.add_argument('-i', '--item', action='store', dest='alist',
                    type=str, nargs='*', default=['item1', 'item2', 'item3'],
                    help="Examples: -i item1 item2, -i item3")
opts = parser.parse_args()

print("List of items: {}".format(opts.alist))

참고 : 목록에 저장된 여러 문자열 인수를 수집하고 있습니다-opts.alist 정수 목록을 원하면 parser.add_argument의 type 매개 변수를 int로 변경하십시오.

실행 결과 :

python3.6 temp_agrs1.py -i item5 item6 item7
List of items: ['item5', 'item6', 'item7']

python3.6 temp_agrs1.py -i item10
List of items: ['item10']

python3.6 temp_agrs1.py
List of items: ['item1', 'item2', 'item3']

1
@Py_minion 목록을 인수로 사용하고 출력을 목록으로 사용하는 방법이 있습니까? temp_args1.py -i [item5 ,item6, item7]출력도 중첩 목록 대신 목록으로 표시됩니다.
Moondra

@ 문 드라 네. 다행 이네 ```parser.add_argument ( '-o', '--options', action = 'store', dest = 'opt_list', type = str, nargs = '*', default = sample_list, help = "데이터베이스 문자열 공백으로 구분됩니다 예 : \ -o option1 option2, -o option3 ")```여기서 'sample_list'는 기본 옵션이있는 list 유형입니다. 예 : sample_list = [option4, option5]
Py_minion

1
@Py_minion 감사합니다. 오늘 나중에 테스트하려고합니다.
Moondra

나는 이것을 사용했다. 이것은 인수로부터리스트를 생성하는 데 매우 유용하다.
siby 2016 년

5

단일 스위치가 여러 매개 변수를 사용하도록하려면을 사용 nargs='+'합니다. 예제 '-l'이 실제로 정수를 사용하는 경우 :

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    nargs='+',       # one or more parameters to this switch
    type=int,        # /parameters/ are ints
    dest='list',     # store in 'list'.
    default=[],      # since we're not specifying required.
)

print a.parse_args("-l 123 234 345 456".split(' '))
print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))

생산

Namespace(list=[123, 234, 345, 456])
Namespace(list=[456])  # Attention!

동일한 인수를 여러 번 지정하면 기본 작업 ( 'store')이 기존 데이터를 대체합니다.

대안은 append조치 를 사용하는 것입니다 .

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    type=int,        # /parameters/ are ints
    dest='list',     # store in 'list'.
    default=[],      # since we're not specifying required.
    action='append', # add to the list instead of replacing it
)

print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))

어느 생산

Namespace(list=[123, 234, 345, 456])

또는 쉼표로 구분 된 값을 구문 분석하기 위해 사용자 정의 핸들러 / 액션을 작성할 수 있습니다.

-l 123,234,345 -l 456

5

에서는 add_argument(), type단지 문자열 반환 옵션 값을받는 호출 객체입니다.

import ast

def arg_as_list(s):                                                            
    v = ast.literal_eval(s)                                                    
    if type(v) is not list:                                                    
        raise argparse.ArgumentTypeError("Argument \"%s\" is not a list" % (s))
    return v                                                                   


def foo():
    parser.add_argument("--list", type=arg_as_list, default=[],
                        help="List of values")

이를 통해 다음을 수행 할 수 있습니다.

$ ./tool --list "[1,2,3,4]"

문자열을 전달해야하는 경우이 방법을 사용하려면 명령 줄에서 적절하게 인용해야합니다. 사용자가이 예기치 않은 것을 발견 할 수 있습니다. 정수만 구문 분석하면 괜찮습니다.
SethMMorton

1

내부 목록의 유형과 길이가 다른 중첩 목록이 있고 유형을 유지하려는 경우 (예 :

[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]

당신은에 의해 제안 된 솔루션을 사용할 수 있습니다 SAM-메이슨 @를이 질문에 아래와 같이 :

from argparse import ArgumentParser
import json

parser = ArgumentParser()
parser.add_argument('-l', type=json.loads)
parser.parse_args(['-l', '[[1,2],["foo","bar"],[3.14,"baz",20]]'])

이것은 다음을 제공합니다.

Namespace(l=[[1, 2], ['foo', 'bar'], [3.14, 'baz', 20]])

0

여러 목록, 정수 값 및 문자열 전달을 처리하고 싶습니다.

유용한 링크 => Bash 변수를 파이썬에 전달하는 방법?

def main(args):
    my_args = []
    for arg in args:
        if arg.startswith("[") and arg.endswith("]"):
            arg = arg.replace("[", "").replace("]", "")
            my_args.append(arg.split(","))
        else:
            my_args.append(arg)

    print(my_args)


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

순서는 중요하지 않습니다. 목록을 전달하려면 사이 "[""]같이 쉼표를 사용하여 분리하십시오.

그때,

python test.py my_string 3 "[1,2]" "[3,4,5]"

출력 => ['my_string', '3', ['1', '2'], ['3', '4', '5']], my_args변수에는 인수가 순서대로 포함됩니다.


0

가장 우아한 해결책은 Chepner가 언급 한 것처럼 람다 함수를 "type"으로 전달하는 것입니다. 이 외에도 목록의 구분 기호를 미리 모르는 경우 여러 구분 기호를 전달하여 다시 분리 할 수 ​​있습니다.

# python3 test.py -l "abc xyz, 123"

import re
import argparse

parser = argparse.ArgumentParser(description='Process a list.')
parser.add_argument('-l', '--list',
                    type=lambda s: re.split(' |, ', s),
                    required=True,
                    help='comma or space delimited list of characters')

args = parser.parse_args()
print(args.list)


# Output: ['abc', 'xyz', '123']

-l예제 전화에서 의미 했습니까 ? 어디 -n에서 왔습니까?
앤서니

또한 솔루션은 Python 3.8.2에서 작동하지 않습니다. 코드는 다음과 같습니다 parser.add_argument('-l', '--list', type = lambda s: re.split('[ ,;]', s)).. 입력은 다음과 같습니다 script.py -l abc xyz, abc\nxyz.. 마지막으로 결과는 다음과 같습니다.script.py: error: unrecognized arguments: xyz, abcnxyz
Anthony Anthony 13:19의

작동하도록 내 예제를 변경하십시오. :)
Nebulastic
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.