使用subprocess.Popen时出现Python内存分配错误

使用subprocess.Popen时出现Python内存分配错误,python,memory-management,subprocess,Python,Memory Management,Subprocess,我在做一些生物信息学的工作。我有一个python脚本,在某一点上调用一个程序来执行一个昂贵的过程(序列对齐..使用大量的计算能力和内存)。我使用subprocess.Popen将其称为。当我在一个测试用例上运行它时,它完成并很好地完成了。然而,当我在完整的文件上运行它时,它将不得不对不同的输入集执行多次操作,它会死掉。子进程抛出: OSError: [Errno 12] Cannot allocate memory 我发现了一些类似问题的链接,但我不确定它们是否适用于我的情况 默认情况下,序列

我在做一些生物信息学的工作。我有一个python脚本,在某一点上调用一个程序来执行一个昂贵的过程(序列对齐..使用大量的计算能力和内存)。我使用subprocess.Popen将其称为。当我在一个测试用例上运行它时,它完成并很好地完成了。然而,当我在完整的文件上运行它时,它将不得不对不同的输入集执行多次操作,它会死掉。子进程抛出:

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
抛出错误


Edit2:在64位ubuntu 10.4上运行Python2.6.4,我会在64位操作系统上运行64位python

使用32位,在操作系统开始告诉您不再需要内存之前,您只能获得3 GB的内存

另一种选择可能是使用内存映射文件打开文件:


编辑:啊,你是64位的。。可能是因为RAM+交换空间不足。。修复方法可能是增加交换量。

这与Python或
子流程
模块没有任何关系
subprocess.Popen
只是向您报告它从操作系统接收到的错误。(顺便问一下,您使用的是什么操作系统?)来自Linux上的
man 2 fork

ENOMEM    fork()  failed  to  allocate  the  necessary  kernel  structures
          because memory is tight.

您是否多次调用
subprocess.Popen
?如果是这样的话,那么我认为您能做的最好的事情就是确保在下一次调用之前终止并收获您流程的上一次调用。

是否使用subprocess.PIPE?我有问题,当它被使用时,我读到了问题。临时文件通常可以解决这个问题。

6年后,我为这一操作感到非常抱歉,没有人提到这是Unix中非常常见的问题,实际上与python或生物信息学无关。对os.fork()的调用会临时将父进程的内存增加一倍(父进程的内存必须可供子进程使用),然后将其全部丢弃以执行exec()。虽然并不总是实际复制此内存,但系统必须有足够的内存来允许复制它,因此,如果您是父进程,则使用了超过一半的系统内存,并且您的子进程甚至输出了“wc-l”,那么您将遇到内存错误

解决方案是使用posix_spawn,或在脚本开始时创建所有子进程,而内存消耗较低,然后在父进程完成内存密集型任务后再使用它们


使用keyworks“os.fork”和“memory”的google搜索将显示几个关于该主题的堆栈溢出帖子,可以进一步解释发生了什么:)

我多次调用它,但都是连续调用的。我在其中抛出一个子进程.communicate(),因为我希望每个进程都有标准输出。另外,如果这是内存不足的情况,为什么linux不使用交换文件(这台机器是共享资源,有64g ram,所以我认为它没有定义的交换空间)?@jmerkin,使用
swapon-s
来判断是否配置了任何交换,使用
free
告诉您有多少可用物理内存和交换空间。如果您没有交换,配置交换是增加可用虚拟内存的一种方法。另外,我建议你回答@Konstantin Tenzin的问题。您是否实际使用了子流程的结果(stdout/stderr)?如果是这样,结果是否很大?如果是这样,您将如何确保Python进程不会消耗所有可用内存?是的,交换和内存非常丰富。我正在使用stdout的结果,它最多只有几兆字节。不管怎样,我都想把它写入一个文件。我已经尝试使用stdout=subprocess.PIPE以及subprocess.Popen('foo>bar',shell=True,stderr=subprocess.PIPE)将其写入文件。两者都给出了错误。@jmerkin,
stdout
参数可以接受“文件对象”,例如
subprocess.Popen(“foo”,stdout=open(“bar”,“w”))
ulimit-a
报告了什么令人惊讶的事情吗?我在两端运行64位。与常规文件相比,使用内存映射文件的优势是什么?一个优势是,您可以告诉操作系统优化随机或顺序访问,并且您可以打开和分块大于RAM的文件。内存映射文件的缺点是,如果您的机器意外停机,他们很容易腐败,我两种方法都试过了。我尝试直接写入文件和subprocess.PIPE:a=subprocess.Popen('foo>bar',shell=True,stderr=subprocess.PIPE);a、 wait())a=subprocess.Popen(foo,stdout=subprocess.PIPE,stderr=subprocess.PIPE)f_out.write(a.communicate()[0]),这也给了我这个错误。Stderr几乎可以忽略不计,最多只有几行关于程序的进度,所以它应该不会太多。您可以从命令行以独立模式执行子流程程序吗?能否启动几个实例,将它们设置为后台(使用
&
终止命令)?运行
time-vfoo…
获取程序使用计算机资源的一些统计数据怎么样?