【发布时间】:2016-04-13 11:00:54
【问题描述】:
使用下面的代码,p.returncode 始终是None。根据Popen.returncode documentation,这意味着这个过程还没有结束。
为什么我没有收到退出代码?
import os
import sys
import subprocess
cmd = ['echo','hello']
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
try:
# Filter stdout
for line in iter(p.stdout.readline, ''):
sys.stdout.flush()
# Print status
print(">>> " + line.rstrip())
sys.stdout.flush()
except:
sys.stdout.flush()
print 'RETURN CODE', p.returncode
请注意:我单独读取每一行的原因是因为我想实时过滤其他长时间运行的进程的输出并根据某些字符串停止它们。
我使用的是 Python 2.7.5(CentOS 7 64 位)。
解决方案
感谢@skyking 发布的答案,我现在可以使用Popen.poll() 成功捕获这样的退出代码(Popen.wait() 使我的进程陷入僵局):
import os
import sys
import subprocess
import time
cmd = ['echo','hello']
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
try:
# Filter stdout
for line in iter(p.stdout.readline, ''):
sys.stdout.flush()
# Print status
print(">>> " + line.rstrip())
sys.stdout.flush()
except:
sys.stdout.flush()
# Wait until process terminates (without using p.wait())
while p.poll() is None:
# Process hasn't exited yet, let's wait some
time.sleep(0.5)
# Get return code from process
return_code = p.returncode
print 'RETURN CODE', return_code
# Exit with return code from process
sys.exit(return_code)
【问题讨论】:
-
顺便说一句,你可以用
iter(p.stdout, ...)代替iter(p.stdout.readline, ...) -
@zondo 不确定 Python 2,但在 Python 3 中,您绝对也可以直接遍历
p.stdout而无需iter(...)- 也许您必须为此设置universal_newlines=TruePopen构造函数虽然... -
@ByteCommander:确实如此(是的,在 Python 2 中也是如此),但
iter的第二个参数并不那么容易实现。 -
@zondo
for line in iter(p.stdout):、for line in p.stdout和for line in iter(p.stdout.readline, ''):都工作相同。如果传递一些支持迭代的东西,也就是一个可迭代的,则不需要 2. 给 iter 的参数。 2 参数形式用于传递可调用对象(p.stdout不是,它是一个文件对象)。还有iter(p.stdout) is p.stdout.
标签: python