web-dev-qa-db-ja.com

オプションとしてリストを渡すためのargparseオプション

リストをコマンドラインプログラムの引数として渡します。リストをオプションとして渡すための 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"
302
user2125827

TL; DR

nargsオプションまたはactionオプションの'append'設定を使用します(ユーザーインターフェイスの動作方法によって異なります)。

nargs

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

nargs='+'は1つ以上の引数を取り、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 !!!を使用しないでください-argparsetype=listを使用する状況はおそらくないでしょう。今まで。


これを行おうとするさまざまな方法のいくつかと、最終結果を詳しく見てみましょう。

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が内部でtypeの値を使用して強制的に個々の特定の引数すべての引数の集合ではなく、選択したtypeを使用するために発生します。
    • type=int(またはその他)を使用して、int(またはその他)のリストを取得できます。

1:一般的な意味ではありません。リストをargparseに渡すに引用符を使用することは、あなたが望むものではありません。

664
SethMMorton

スクリプトの後半で解析する区切り文字列を渡すことを好みます。その理由は以下の通りです。リストはどんなタイプのintまたはstrでも構いません、そして時々nargsを使用する私は複数のオプション引数と位置引数があるなら問題に遭遇します。

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]

うまくいきます。区切り文字もスペースにすることができますが、これは問題の例のように引数値を引用符で囲むことを強制します。

53
dojuba

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')
13
Martin Thoma

単一のスイッチに複数のパラメータを指定する場合は、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
4
kfsone

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]"
4
wonder.mice

Argparseのadd_argumentメソッドで nargsパラメータ を使用する

Add_argumentパラメータとしてnargs = ' 'を使用します。明示的な引数を渡さない場合は、デフォルトでpickle選択するオプションとして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']
2
Py_minion

たぶん最も簡単な答え

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-l", "--tolist", help="input to list", action="store_true")
parser.add_argument("newlist", type=str, help="generate a list")
args = parser.parse_args()
if args.tolist:
    print(args.newlist.split(" "))
2

内側のリストのタイプと長さが異なるネストされたリストがあり、タイプを保持したい場合、たとえば、

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

次に、 @ sam-mason から この質問 で提案されたソリューションを使用できます。

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
Meysam Sadeghi