了解Python分叉和内存分配错误

时间:2013-03-15 22:41:13

标签: python linux fork

我有一个内存密集型的Python应用程序(介于几百MB到几GB之间) 我有一些主要应用程序需要运行的非常小的Linux可执行文件,例如。

child = Popen("make html", cwd = r'../../docs', stdout = PIPE, shell = True)
child.wait()

当我使用subprocess.Popen运行这些外部实用程序(一次,在长主流程运行结束时)时,我有时会得到OSError: [Errno 12] Cannot allocate memory
我不明白为什么......请求的过程很小!
系统有足够的内存用于更多的shell。

我正在使用Linux(Ubuntu 12.10,64位),所以我想子进程调用Fork 而Fork分叉我现有的进程,因此消耗的内存量增加了一倍,并且失败了 “写字复制”怎么了?

我可以在没有fork的情况下生成一个新进程(或者至少没有复制内存 - 从新开始)?

相关:

The difference between fork(), vfork(), exec() and clone()

fork () & memory allocation behavior

Python subprocess.Popen erroring with OSError: [Errno 12] Cannot allocate memory after period of time

Python memory allocation error using subprocess.Popen

1 个答案:

答案 0 :(得分:3)

似乎没有真正的解决方案(即使用vfork的子进程的替代实现)。那么一个可爱的黑客怎么样?在您的过程开始时,生成一个挂起的内存很小的内存,准备生成您的子进程,并在主进程的整个生命周期中保持与它的开放式通信。

这是一个使用rfoo(http://code.google.com/p/rfoo/)和一个名为rfoosocket的命名unix套接字的例子(显然你可以使用rfoo支持的其他连接类型,或者另一个RPC库):

服务器:

import rfoo
import subprocess

class MyHandler(rfoo.BaseHandler):
    def RPopen(self, cmd):
        c = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
        c.wait()
        return c.stdout.read()

rfoo.UnixServer(MyHandler).start('rfoosocket')

客户端:

import rfoo

# Waste a bunch of memory before spawning the child. Swap out the RPC below
# for a straight popen to show it otherwise fails. Tweak to suit your
# available system memory.
mem = [x for x in range(100000000)]

c = rfoo.UnixConnection().connect('rfoosocket')

print rfoo.Proxy(c).RPopen('ls -l')

如果您需要与生成的子流程进行实时来回的协处理交互,这个模型可能无法正常工作,但您可能会破解它。您可能想要清理可用的args根据您的具体需求传递给Popen,但这一切都应该相对简单。

您还应该直接在客户端启动时启动服务器,并管理退出时要清理的套接字文件(或端口)。