我试图将一个列表作为参数传递给命令行程序。是否有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"

当前回答

如果你想让一个开关有多个参数,那么你可以使用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='lst',      # store in 'lst'.
    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(lst=[123, 234, 345, 456])
Namespace(lst=[456])  # Attention!

如果多次指定相同的参数,默认操作('store')将替换现有数据。

另一种方法是使用追加操作:

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    type=int,        # /parameters/ are ints
    dest='lst',      # store in 'lst'.
    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(lst=[123, 234, 345, 456])

或者您可以编写一个自定义处理程序/操作来解析逗号分隔的值,这样您就可以这样做

-l 123,234,345 -l 456

其他回答

我认为最优雅的解决方案是传递一个lambda函数给“类型”,正如Chepner所提到的。除此之外,如果你事先不知道列表的分隔符是什么,你也可以传递多个分隔符给re.split:

# 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']

我想处理传递多个列表,整数值和字符串。

如何将Bash变量传递给Python?

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]"

Output => ['my_string', '3', ['1', '2'], ['3', '4', '5']]], my_args变量按顺序包含参数。

将chepner的评论应用到Lunguini的回答中:

import argparse, json                                                                                            
parser = argparse.ArgumentParser()                                                                               
parser.add_argument('-l', '--list', type=lambda a: json.loads(a), default="[]",                                  
                    help="String formatted as list wrapped in []")                                               
args = parser.parse_args()                                                                                       
print(args.list)                                                                                                 

用法:

$ python parse_list.py -l "[265340, 268738, 270774, 270817]"
[265340, 268738, 270774, 270817]

如果你有一个嵌套列表,其中内部列表有不同的类型和长度,你想要保留类型,例如:

[[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]])

简短的回答

使用nargs选项或action选项的“append”设置(取决于您希望用户界面如何表现)。

纳尔格斯

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

Nargs ='+'接受一个或多个参数,Nargs ='*'接受零或多个参数。

附加

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!!-可能在任何情况下你都不需要在argparse中使用type=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']

外卖:

Use nargs or action='append' nargs can be more straightforward from a user perspective, but it can be unintuitive if there are positional arguments because argparse can't tell what should be a positional argument and what belongs to the nargs; if you have positional arguments then action='append' may end up being a better choice. The above is only true if nargs is given '*', '+', or '?'. If you provide an integer number (such as 4) then there will be no problem mixing options with nargs and positional arguments because argparse will know exactly how many values to expect for the option. Don't use quotes on the command line1 Don't use type=list, as it will return a list of lists This happens because under the hood argparse uses the value of type to coerce each individual given argument you your chosen type, not the aggregate of all arguments. You can use type=int (or whatever) to get a list of ints (or whatever)


他说:我不是说一般情况。我的意思是使用引号将列表传递给argparse不是你想要的。