如何在Python中将整个列表作为命令行参数传递?

65

我试图将包含整数的两个列表作为参数传递给Python代码。但是sys.argv[i]将参数作为字符串列表获取。

输入看起来像:

$ python filename.py [2,3,4,5] [1,2,3,4]

我找到了以下的技巧来将列表转换。

strA = sys.argv[1].replace('[', ' ').replace(']', ' ').replace(',', ' ').split()
strB = sys.argv[2].replace('[', ' ').replace(']', ' ').replace(',', ' ').split()
A = [float(i) for i in strA]
B = [float (i) for i in strB]

有没有更好的方法来做这件事?


你可以了解序列化技术;当我需要通过命令行传递类似列表结构的参数时,这通常是我所做的。你也可以研究JSON或其他形式的数据序列化。(但在深入解决方案之前,我会确保通过命令行传递列表作为参数确实是你需要的,并且这不是一个X-Y问题) - Chris Sprague
为什么不使用 lists = [[int(el) for el in arg[1:-1].split(',')] for arg in sys.argv[1:]] 呢?在这种情况下,您可以看到括号是相当无用的。 - Radio Controlled
9个回答

133

不要重复发明轮子。使用argparse模块,明确详细地传递参数列表。

import argparse
# defined command line options
# this also generates --help and error handling
CLI=argparse.ArgumentParser()
CLI.add_argument(
  "--lista",  # name on the CLI - drop the `--` for positional/required parameters
  nargs="*",  # 0 or more values expected => creates a list
  type=int,
  default=[1, 2, 3],  # default if nothing is provided
)
CLI.add_argument(
  "--listb",
  nargs="*",
  type=float,  # any type/callable can be used here
  default=[],
)

# parse the command line
args = CLI.parse_args()
# access CLI options
print("lista: %r" % args.lista)
print("listb: %r" % args.listb)

你可以使用以下方式来调用它

$ python my_app.py --listb 5 6 7 8 --lista  1 2 3 4
lista: [1, 2, 3, 4]
listb: [5.0, 6.0, 7.0, 8.0]

1
这是目前最好的答案。只需使用argparse的nargs即可。 - Qinsi
1
@MisterMiyagi 涂蜡,擦蜡 - mLstudent33
这是更好的编程实践。谢谢。 - Iddo weiner

25

命令行参数始终作为字符串传递。您需要自己将它们解析成所需的数据类型。

>>> input = "[2,3,4,5]"
>>> map(float, input.strip('[]').split(','))
[2.0, 3.0, 4.0, 5.0]
>>> A = map(float, input.strip('[]').split(','))
>>> print(A, type(A))
([2.0, 3.0, 4.0, 5.0], <type 'list'>)

有一些类似于argparseclick的库,可以让你定义自己的参数类型转换,但是argparse会将"[2,3,4]"[2,3,4]视为相同的,所以我怀疑它不会有用。

2019年1月编辑 这个回答似乎仍然受到关注,所以我将直接引用来自argparse文档的另一个选项。

您可以使用action=append来允许收集重复参数到单个列表中。

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--foo', action='append')
>>> parser.parse_args('--foo 1 --foo 2'.split())
Namespace(foo=['1', '2'])
在这种情况下,您需要为每个列表项传递--foo ?一次。使用 OP 的示例:python filename.py --foo 2 --foo 3 --foo 4 --foo 5 将导致 foo=[2,3,4,5]

1
print(A) 输出一个 <map object> - kev
将A转换为列表,例如:A = list(map(int, input.strip('[]').split(','))) print(A, type(A)) - CognitiveRobot
我最初在2015年使用Python2编写了这个程序,其中map函数返回一个列表。而Python 3确实返回一个map(迭代器)。 - Josh J
1
所以请将这些信息添加到您的原始答案中,以便更加明确。 - Fred

22

我在我的端上测试了这个,我的输入看起来是这样的:

python foo.py "[1,2,3,4]" "[5,6,7,8,9]"

我正在执行以下操作以转换这两个参数:

import ast
import sys

list1 = ast.literal_eval(sys.argv[1])
list2 = ast.literal_eval(sys.argv[2])

4
抛出ValueError: malformed node or string: <_ast.Name object at 0x0000024929290518>,我的参数是"[n01530575,n01530576]" - user924

16

为什么不呢:

python foo.py 1,2,3,4 5,6,7,8  
比尝试评估Python代码要干净得多,并且不需要用户了解Python格式。
import sys

list1 = sys.argv[1].split(',')
list2 = [int(c) for c in sys.argv[2].split(',')]  # if you want ints

11

您还可以执行以下操作:

比如,您有foo.py

import json
import sys
data = json.loads(sys.argv[1])
print data, type(data)

然后如果你按以下方式运行:python foo.py "[1,2,3]"

输出结果:

[1, 2, 3] <type 'list'>


2
它抛出了json.decoder.JSONDecodeError: Expecting value: line 1 column 2 (char 1)错误。 - user924
1
我的参数是"[n01530575,n01530576]" - user924

6
您可以简单地使用 argparse 的 nargs='+' 选项。
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--myarg', dest='myarg', required=False, help='--myarg 100 100 100 takes a list of 3 elements, each is of value 100 ', nargs='+', type=int, default=[100,100,100])

您可以像这样传递参数:
python your_file.py --myarg 1 2 3

这将以[1,2,3]的形式存储在你的程序中,存储在myarg中。
print(myarg)

输出:

[1,2,3]

4

不,无法在命令行参数中传递列表。命令行参数始终为字符串。但是有一种更好的方法将其转换为列表。您可以像这样执行:

import ast

A = ast.literal_eval(strA)
B = ast.literal_eval(strB)

3

你需要进行转义:

python some.py \[2,3,4,5\] \[1,2,3,4\]

some.py

import sys

print sys.argv[1]
print sys.argv[2]

这让我想到:
[2,3,4,5]
[1,2,3,4]

Bash out

更新:

import sys
import ast

d = ast.literal_eval(sys.argv[1])
b = ast.literal_eval(sys.argv[2])

for a in d:
    print a

for e in b:
    print e

首先,我们将提供:

2
3
4
5

第二个将会提供

1
2
3
4

当你打印你所做的事情的类型时,会发生什么? - postelrich
当你输出类型时,它仍然会返回一个字符串。 - idjaw
我已经更新了答案。但是我现在发现它与https://dev59.com/iFwY5IYBdhLWcg3wU2XA#32762516相同。 - pregmatch

0

你也可以使用以下方式:

假设你正在尝试将一组数字传递给 Python 代码:

python3 check.py --ids 25,36

在代码中,您只需要按以下方式读取ID:

list(eval(args.ids))

然后你会看到:

[25,36]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接