使用subprocess.Popen时的Python内存分配错误
我正在做一些生物信息学的工作。我有一个Python脚本,其中有一部分会调用一个程序来进行一个耗费计算资源的过程(序列比对……这需要大量的计算能力和内存)。我使用subprocess.Popen来调用它。当我在一个测试案例上运行时,它完成得很好。但是,当我在完整文件上运行时,因为它需要对不同的输入集多次执行这个过程,就出现了问题,程序崩溃了。Subprocess抛出了:
OSError: [Errno 12] Cannot allocate memory
我找到了一些链接,讨论了类似的问题,分别在这里、这里和这里,但我不确定这些是否适用于我的情况。
默认情况下,序列比对程序会尝试请求51000M的内存。它并不总是会使用这么多,但有可能会。在加载和处理完整输入时,这么多内存是不可用的。然而,即使我限制它请求的内存量,或者尝试使用较低的可用内存,仍然会出现同样的错误。我也尝试过将shell设置为True,但结果一样。
这个问题困扰了我几天了。谢谢大家的帮助。
编辑:扩展一下错误追踪信息:
File "..../python2.6/subprocess.py", line 1037, in _execute_child
self.pid=os.fork()
OSError: [Errno 12] Cannot allocate memory
抛出了这个错误。
编辑2:在64位的Ubuntu 10.4上运行Python 2.6.4
4 个回答
我建议在64位的操作系统上运行64位的Python。
如果你用的是32位的系统,实际上你只能使用大约3GB的内存,之后系统就会告诉你不能再用了。
另外一个选择是使用内存映射文件来打开文件:
http://docs.python.org/library/mmap.html
补充:哦,你是在用64位的系统……可能的原因是你的内存和交换空间都用完了……解决办法可能是增加交换空间的大小。
这跟Python或者subprocess
模块没有关系。subprocess.Popen
只是把它从操作系统那里收到的错误信息告诉你。顺便问一下,你用的是什么操作系统呢?在Linux上可以查阅man 2 fork
的内容:
ENOMEM fork() failed to allocate the necessary kernel structures
because memory is tight.
你是不是多次调用了subprocess.Popen
?如果是这样的话,最好的办法就是确保在下一次调用之前,前一次的进程已经结束并被清理掉。
我真的很同情提问者。六年过去了,居然没有人提到这是Unix中一个非常常见的问题,实际上和python或生物信息学没有关系。当你调用os.fork()时,父进程的内存会暂时翻倍(因为子进程需要访问父进程的内存),然后再把这些内存丢掉,去执行exec()。虽然这部分内存不一定会被实际复制,但系统必须有足够的内存来支持这种复制。因此,如果你的父进程使用的内存超过了系统内存的一半,即使你只是执行“wc -l”这样的简单命令,也会遇到内存错误。
解决办法是使用posix_spawn,或者在脚本开始时创建所有的子进程,这样内存使用量较低,然后在父进程完成内存密集型操作后再使用这些子进程。
如果你在谷歌上搜索“os.fork”和“memory”这两个关键词,会找到几个相关的Stack Overflow帖子,能进一步解释发生了什么哦 :)