我有一个内存密集型的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()
答案 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,但这一切都应该相对简单。
您还应该直接在客户端启动时启动服务器,并管理退出时要清理的套接字文件(或端口)。