了解Python的叉子和内存分配错误(Understanding Python fork and m

2019-07-21 18:16发布

我有一个内存密集型的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
我不明白为什么......请求的过程是很小的!
该系统具有更多的炮弹足够的内存。

我使用Linux(Ubuntu的12.10,为64位),所以我想子进程调用fork。
和叉叉我的现有过程,从而倍增所消耗的存储器量,并且将失败?
发生了什么事“写时复制”?

我可以生成无叉(或至少不复制内存 - 开始新)一个新的进程?

有关:

()叉(),vfork的(),exec()和克隆之间的差

叉()&存储器分配行为

蟒subprocess.Popen与OSERROR示数:[错误12]无法的时间段之后分配内存

使用subprocess.Popen Python的内存分配错误

Answer 1:

它不会出现一个真正的解决方案将是即将到来的(即替代实现子,它使用的vfork)。 因此,如何一个可爱的黑客? 在你的进程的开始,生成一个奴隶是整天与小内存占用,准备产卵的子过程,并保持开放的沟通,它在整个过程中主要的生活。

下面是使用rfoo(一个例子http://code.google.com/p/rfoo/与命名Unix套接字称为rfoosocket)(你能明显使用其他连接类型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')

如果您需要实时来回协进程的互动与你的子进程催生了这种模式可能不会工作,但你也许可以破解它,你可能会想清理可以传递到POPEN可用ARGS根据您的具体需求,但都应该是相对比较简单。

你也应该发现它可以直接在客户端开始启动服务器,以管理套接字文件(或端口)退出时被清理。



文章来源: Understanding Python fork and memory allocation errors