我有一个内存密集型的Python应用程序(介于几百MB到几GB之间).
我有几个非常小的Linux可执行文件,主应用程序需要运行,例如
child = Popen("make html", cwd = r'../../docs', stdout = PIPE, shell = True)
child.wait()
Run Code Online (Sandbox Code Playgroud)
当我运行这些外部实用程序(一次,在长主进程运行结束时)使用subprocess.Popen我有时得到OSError: [Errno 12] Cannot allocate memory.
我不明白为什么......请求的过程很小!
系统有足够的内存用于更多的shell.
我正在使用Linux(Ubuntu 12.10,64位),所以我猜Subprocess调用了Fork.
而Fork分叉我现有的进程,从而使消耗的内存量增加一倍,并且失败了?
"写字复制"怎么了?
我可以在没有fork的情况下生成一个新进程(或者至少没有复制内存 - 重新启动)?
有关:
fork(),vfork(),exec()和clone()之间的区别
似乎不会出现真正的解决方案(即使用 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')
Run Code Online (Sandbox Code Playgroud)
客户:
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')
Run Code Online (Sandbox Code Playgroud)
如果您需要与生成的子进程进行实时来回协进程交互,则此模型可能无法工作,但您可能能够破解它。您可能想要清理可以传递给 Popen 的可用参数根据您的具体需求,但这应该相对简单。
您还应该发现在客户端启动时启动服务器以及管理在退出时清理的套接字文件(或端口)非常简单。
| 归档时间: |
|
| 查看次数: |
5482 次 |
| 最近记录: |