在子进程调用中将列表作为参数传递给python脚本

时间:2017-09-08 10:46:34

标签: python list

我正在使用Subprocess调用从主脚本执行Insert_API。要插入的值存储在列表中,我需要在子进程调用时将列表作为参数传递。它给我一个错误,说参数必须是字符串。如果我创建str(列表)然后它工作但插入不能正常工作,因为它作为字符串传递而不是列表。尝试传递为字符串并再次转换为脚本中的列表,但也无法正常工作。 有没有办法按原样传递List?每次都有2个列表可以通过。请告诉我,如果有任何方法可以在子进程调用中传递2个列表? 示例代码:

subprocess.check_output(["python","Metadata_Index_EAV_LOAD.py",Dataset1,MetaDataIndex_Table,SchemaFields,FieldValues,r_date])

SchemaField和result是我需要作为参数传递的两个列表。

3 个答案:

答案 0 :(得分:0)

您可以在mainScript中设置argparse以使用

处理输入参数
parser = argparse.ArgumentParser()
parser.add_argument('-sf','--schema_field', action='append', help="List of id's")
args = parser.parse_args()

这样在您的命令行参数中,您只需通过重用快捷方式将id添加到列表中。

python -c mainScript.py -sf 1001 -sf 1002 -sf 1003

这应该将args.schema_field作为mainScript中的列表返回。

处理复杂的可选和位置命令行参数绝对是argparse的工作 - 所以我建议在这里查看官方文档:https://docs.python.org/2/howto/argparse.html

答案 1 :(得分:0)

您可能会找到一种将参数作为列表传递的方法,例如建议的in this answer,但仍然可以使用json.loads方法更简单的解决方案。

不要运行list(SchemaFields),而是尝试运行类似:

import json
schema_list = json.loads(SchemaFields)
values = json.loads(FieldValues)

你可能不得不继续将参数作为字符串发送。

尽管如此,我同意Roseman的评论,看起来如果你使用了一些基类来准备好所有这些操作并且只是从你的主脚本中调用它们这会更简单(不确定你的硬编码意味着什么)以这种方式评估,因为您仍然可以在主脚本中发送sys.args输入。

答案 2 :(得分:0)

也许您希望通过args传递列表,但这不应该这样做。 为什么?因为传递给内核的命令行的长度是有限的。最新的Linux发行版接受相当长的字符串,但仍然。如果你有很多可以包含特殊字符的东西等等,它有时可能会非常错误。特别是如果你将接收器脚本的使用给其他人,他们可以忘记绕过shell并将数据直接发送到你的脚本。在这种情况下,整个混乱可能会上升。

所以,我建议你使用烟斗。即在接收器中从sys.stdin读取,在发送器中使用Popen()。communic()。 像这样:

# Receiver:
from cPickle import loads
import sys

data = sys.stdin.read() # This will return after '^D' is received.
data = loads(data)
print "I received:"
for x in data:
    print x
    print "\t", data[x]

# Sender:
from cPickle import dumps
from subprocess import Popen, PIPE

data = {"list1": [1, 2, 3, 4],
    "list2": [3, 4, 5, 6]}
cmd = ["python", "receiver.py"]
p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
result, error = p.communicate(dumps(data))
if error:
    raise Exception(error)
print "Receiver sent:"
print result

现在,如果其他人不需要使用Python将数据发送到您的脚本,那么不要像另一个答案中建议的那样使用pickling而是使用json。 或者您甚至可以使用literal_eval():

# In receiver:
from ast import literal_eval
import sys

data = sys.stdin.read()
data = literal_eval(data)
#...

# And in sender:
# ...
result, error = p.communicate(repr(data))
#...

literal_eval()是eval()的安全版本,它只评估内置数据类型,而不是表达式和​​其他对象。

如果你仍然坚持使用args,那么你应该使用类似的东西:

list1 = [1, 2, 3, 4]

def convert (l):
    return ",".join((str(x) for x in l))

def get (s):
    return s.split(",")

但是,您必须确保您的分隔符不会出现在字符串中的任何其他位置或构成转义机制。此外,如果您不发送字母数字字符,则必须使用URL安全base64对内容进行编码,以避免与操作系统和/或shell发生冲突。