Python subprocess传递字典、路径参数接收异常问题求解
subprocess参数传递异常解决方案
问题根因
- 第一次实现的问题:
shell=True与列表形式的命令参数混用:Windows平台下开启shell=True时,只有列表第一个元素会被系统解析为命令内容,后续参数会被直接丢弃,导致路径完全没传递。- 字典类型不能直接作为命令行参数传递:命令行参数只支持字符串格式,直接传入字典会被Python自动转为
repr(字典)的形式,内容会截断、格式异常,所以只能收到部分字典内容。
- 第二次实现的问题:
你将参数编码传入stdin后,子进程没有主动从标准输入读取数据,自然收不到任何参数,和bufsize参数无关。另外自定义!作为分隔符的方案存在风险,如果字典内容或者路径本身包含!会导致参数解析错误。
解决方案
分两种常用实现方式:
方案1:命令行参数传递(适合字典体积较小的场景)
优点是实现简单,不需要修改子进程的读入逻辑太多,注意关闭shell=True即可,父进程代码:
import subprocess import json import sys # 构造参数:先把字典转成JSON字符串 dict_arg = json.dumps(arg[0], ensure_ascii=False) path1_arg = arg[1] path2_arg = arg[2] kwargs = {"stdin": subprocess.PIPE, "stdout": subprocess.PIPE, "stderr": subprocess.PIPE, "env": env} # 关闭shell=True,直接传列表参数,避免参数丢失 with subprocess.Popen([interpreter, r'..\another_project\another_file.py', dict_arg, path1_arg, path2_arg], **kwargs, bufsize=-1) as proc: out, err = proc.communicate() if err: print(err.decode('utf-8', errors='ignore'))
子进程(another_file.py)接收代码:
import sys import json if __name__ == '__main__': # sys.argv[0]是脚本本身路径,从1开始拿参数 dict_data = json.loads(sys.argv[1]) path1 = sys.argv[2] path2 = sys.argv[3] # 后续生成json文件的逻辑
方案2:标准输入传递(适合字典体积大、无命令行长度限制的场景)
不需要自定义分隔符,直接把三个参数打包成一个JSON对象序列化传递,父进程代码:
import subprocess import json # 打包所有参数为一个JSON对象,避免分隔符冲突 all_args = { "dict_data": arg[0], "path1": arg[1], "path2": arg[2] } arg_bytes = json.dumps(all_args, ensure_ascii=False).encode('utf-8') kwargs = {"stdin": subprocess.PIPE, "stdout": subprocess.PIPE, "stderr": subprocess.PIPE, "env": env} with subprocess.Popen([interpreter, r'..\another_project\another_file.py'], **kwargs, bufsize=-1) as proc: out, err = proc.communicate(input=arg_bytes) if err: print(err.decode('utf-8', errors='ignore'))
子进程(another_file.py)接收代码:
import sys import json if __name__ == '__main__': # 从标准输入读全部内容反序列化 input_data = sys.stdin.read() all_args = json.loads(input_data) dict_data = all_args["dict_data"] path1 = all_args["path1"] path2 = all_args["path2"] # 后续生成json文件的逻辑
注意事项
- 非必要不要开启
shell=True,不仅会导致参数传递异常,还会有命令注入的安全风险。 - 涉及中文路径或者中文字典内容时,序列化和反序列化统一使用
utf-8编码,避免乱码。 - 如果必须使用
shell=True,不要传列表形式的命令,直接把完整命令拼成一个字符串传入即可。
内容的提问来源于stack exchange,提问作者DooWon
相关产品推荐
相关产品推荐

