【问题标题】:How to get exit code from subprocess.Popen?如何从 subprocess.Popen 获取退出代码?
【发布时间】: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=True Popen 构造函数虽然...
  • @ByteCommander:确实如此(是的,在 Python 2 中也是如此),但 iter 的第二个参数并不那么容易实现。
  • @zondo for line in iter(p.stdout):for line in p.stdoutfor line in iter(p.stdout.readline, ''): 都工作相同。如果传递一些支持迭代的东西,也就是一个可迭代的,则不需要 2. 给 iter 的参数。 2 参数形式用于传递可调用对象(p.stdout 不是,它是一个文件对象)。还有iter(p.stdout) is p.stdout.

标签: python


【解决方案1】:

根据链接到文档

子返回码,由 poll() 和 wait() 设置(间接由 交流())。 None 值表示该进程尚未终止。

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

您尚未调用pollwait,因此不会设置returncode

另一方面,如果您查看 fx check_output 的源代码,您会发现它们直接使用来自 poll 的返回值来检查返回代码。他们知道该进程已在此时终止,因为他们之前已致电wait。如果您不知道您将不得不调用 wait 方法(但请注意文档中提到的死锁可能性)。

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

【讨论】:

  • 无论我做什么,我都可以使用poll。但它确实适用于wait
  • @fredrik 我通过一些努力也设法获得了这种行为。我猜stdoutstderr 在程序实际终止之前关闭,并且您的python 程序在另一个程序终止之前调用poll
  • 我想我找到了一种让p.poll 工作的方法,因为p.wait 确实让我陷入僵局。我将在我的问题结束时发布我的完整代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-16
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
  • 2021-03-17
  • 2020-12-16
  • 2018-04-18
相关资源
最近更新 更多