python子进程运行适用于单个字符串,但不适用于字符串列表

问题描述

我正在尝试使用 subprocess 模块中的 run 方法从Python脚本中使用命令行选项启动命令行程序。

我的命令定义为指定程序和选项的字符串列表,如下所示(其中pheno_fpconstruction_fp是代表我系统中文件路径的字符串,而exe是代表我正在运行的程序的文件路径):

    step1_cmd = [exe,"--step 1","--p " + pheno_fp,"--b 1000","--o " + construction_fp + "dpw_leaveout"]

不起作用-当我尝试以下操作时,我要运行的程序已启动,但是我指定的命令被错误地解释,因为该程序退出显示错误消息“指定输出文件路径” -o标志”:

    test1 = subprocess.run(step1_cmd)

工作-当我尝试以下操作时,程序将正确执行,这意味着所有参数均按预期进行解释:

    test1 = subprocess.run(" ".join(step1_cmd),shell=True)

如果我正确理解了文档,则建议使用前一种方法,但我不明白为什么它不起作用。我很确定它的格式与文档中的示例相同,因此我有些困惑。有什么想法吗?

解决方法

将每个参数及其值拆分,如下所示:

step1_cmd = [exe,"--step","1","--p",str(pheno_fp),# if it isn't a string already
             "--b","1000","--o",str(construction_fp) + "dpw_leaveout"
]

由于传递参数列表时,每个部分都用空格,选项和它们的值分隔

,

对此行为的解释是here

args是所有调用所必需的,应为字符串或序列 程序参数。通常提供一个参数序列 首选,因为它允许模块处理所有必需的 转义和引用引号(例如,允许文件中有空格 名称)。

示例:序列

l = ['ls','-l tmp'] 

出现错误

subprocess.run(l)                                                                                                                                                      
ls: illegal option --  

这是因为subprocess(这是对Popen的调用)正在尝试运行ls "-l tmp"

定义参数序列的正确方法是将它们分开,以便可以正确引用它们

subprocess.run(['ls','-l','tmp'])