如何从subprocess.Popen获取退出代码?

时间:2016-04-13 11:00:55

标签: python

使用以下代码,p.returncode始终为None。根据{{​​3}},这意味着该过程尚未完成。

为什么我没有收到退出代码?

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)

1 个答案:

答案 0 :(得分:8)

根据链接到文档

  

子返回码,由poll()和wait()设置(间接由    通信())。 “无”值表示该进程尚未终止。

     

负值-N表示孩子被信号N终止(仅限Unix)。

您尚未拨打pollwait,因此returncode无法设置。

另一方面,如果你查看fx check_output的源代码,你会看到他们直接使用poll的返回值来检查返回码。他们知道这个过程已经终止了,因为他们之前已经调过wait。如果您不知道必须调用wait方法(但请注意文档中注明的死锁可能性)。

通常情况下,当您阅读了所有stdout / stderr时程序将会终止,但这并不能保证,这可能是您所看到的。程序或操作系统可以在进程实际终止之前关闭stdout(和stderr),然后在您读取程序的所有输出后立即调用poll可能会失败。