Python:subprocess.Popen和subprocess.call卡住了

17

我使用subprocess.Popen或subprocess.call执行生成大量输出命令行时,Python脚本会停顿。奇怪的是,在等待一段时间后,当脚本处于挂起状态时,我发现被cmd line命令调用的任务已经完成,只有脚本被卡住了。

subprocess.call(cmd, shell = True)
#OR
subprocess.Popen(cmd, stdout = subprocess.PIPE, stdin = subprocess.PIPE, shell = True)
# HANGS HERE
print "show something after subprocess"
请注意,最后一个打印语句从未执行,但实际上cmd已被执行。
请注意,cmd与串口相关,因此当我拔出串口电缆时,一切都变得正常,并且最后的打印语句得到了执行。但是,当我使用终端时,即使串口插入,一切也都正常,这只会出现在Python脚本中。
非常感谢。
2个回答

17
根据Python文档,subprocess.call运行命令并等待其完成,因此它相当于subprocess.Popen后跟Popen.wait
然而,Popen.wait方法的文档明确警告了缓冲区溢出的问题,并建议使用Popen.communicate代替。因此,你需要找到的解决方案应该类似于:
import subprocess
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, shell=True)
stdout, stderr = process.communicate()
print "show something after subprocess"

2
如果您不使用subprocess.PIPE,那么使用subprocess.call没有任何问题,而OP并没有使用它。 - interjay
1
它没有解释为什么print语句的输出不显示在父进程中。即使子进程被阻塞在尝试写入具有完整缓冲区的管道时,Popen()也不会等待子进程。 - jfs
只是补充一下...如果有人需要returncode,在上述情况下可以通过process.returncode访问它。与wait()不同的是,它不会作为communicate()的返回值返回,而是返回一个元组(stdout, stderr)。 - Shailesh Appukuttan

1

我不明白为什么你的第一行代码不起作用——因为没有 stdin/stdout/stderr 重定向,所以没有必要进行阻塞。

第二个代码块应该会在进程

  1. 通过 stdin 接收数据或者
  2. 发送的 stdout 数据超过管道容量而无法读取时

进行阻塞。但是,由于你的子进程正确终止,我看不出还需要阻塞的原因。你确定它真的已经终止了吗?


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