如何在进程终止时清理subprocess.Popen实例

时间:2013-05-02 14:45:14

标签: python python-3.x pyqt subprocess qtwebkit

我有一个在Python / PyQt / QtWebKit基础上运行的JavaScript应用程序,它创建subprocess.Popen个对象来运行外部进程。

Popen个对象保存在字典中并由内部标识符引用,以便JS应用程序可以通过Popen调用pyqtSlot的方法,例如{{1}确定进程是否仍在运行或poll()以杀死流氓进程。

如果某个进程不再运行,我想从字典中删除它的kill()对象以进行垃圾回收。

什么是自动清理字典以防止内存泄漏的推荐方法?

到目前为止我的想法:

  • 在每个衍生进程的线程中调用Popen以在终止时立即执行自动清理 PRO :立即清理,线程可能不会耗费太多CPU功率因为它们应该睡觉,对吧? CON :许多线程取决于产卵活动。
  • 使用线程在所有现有流程上调用Popen.wait(),并检查Popen.poll()是否已终止并在此情况下进行清理。
    PRO :只有一个工作线程用于所有进程,降低内存使用量 CON :必须定期轮询,如果有许多长时间运行的进程或大量已处理的进程,则CPU使用率会更高。

您会选择哪一个?为什么?或者更好的解决方案?

1 个答案:

答案 0 :(得分:2)

对于与平台无关的解决方案,我会使用选项#2,因为高CPU使用率的“CON”可以用类似的东西来规避......

import time

# Assuming the Popen objects are in the dictionary values
PROCESS_DICT = { ... }

def my_thread_main():
    while 1:
        dead_keys = []
        for k, v in PROCESS_DICT.iteritems():
            v.poll()
            if v.returncode is not None:
                dead_keys.append(k)
        if not dead_keys:
            time.sleep(1)  # Adjust sleep time to taste
            continue
        for k in dead_keys:
            del PROCESS_DICT[k]

...因此,如果没有进程在迭代中死亡,你只需要睡一会儿。

因此,实际上,您的线程在大多数时间仍然处于休眠状态,尽管在子进程死亡和随后的“清理”之间存在潜在的延迟,但这确实不是什么大问题,并且这应该比使用时更好。每个进程一个线程。

然而,有更好的平台相关解决方案。

对于Windows,您应该可以通过WaitForMultipleObjects使用ctypes功能作为ctypes.windll.kernel32.WaitForMultipleObjects,但您必须考虑可行性。

对于OSX和Linux,使用SIGCHLD模块异步处理signal可能是最简单的。

一个快速的例子......

import os
import time
import signal
import subprocess

# Map child PID to Popen object
SUBPROCESSES = {}

# Define handler
def handle_sigchld(signum, frame):
    pid = os.wait()[0]
    print 'Subprocess PID=%d ended' % pid
    del SUBPROCESSES[pid]

# Handle SIGCHLD
signal.signal(signal.SIGCHLD, handle_sigchld)

# Spawn a couple of subprocesses
p1 = subprocess.Popen(['sleep', '1'])
SUBPROCESSES[p1.pid] = p1
p2 = subprocess.Popen(['sleep', '2'])
SUBPROCESSES[p2.pid] = p2

# Wait for all subprocesses to die
while SUBPROCESSES:
    print 'tick'
    time.sleep(1)

# Done
print 'All subprocesses died'