如何避免[Errno 12]无法分配使用子流程modu导致的内存错误

2024-04-29 12:37:17 发布

您现在位置:Python中文网/ 问答频道 /正文

完成工作测试用例

当然,取决于本地和远程计算机上的内存,阵列大小将不同。

z1 = numpy.random.rand(300000000,2);
for i in range(1000):
  print('*******************************************\n'); 
  direct_output = subprocess.check_output('ssh blah@blah "ls /"', shell=True);
  direct_output = 'a'*1200000; 
  a2 = direct_output*10;
  print(len(direct_output));

当前用例

如果它有助于我的用例如下:

我发出db查询,然后将结果表存储在远程计算机上。然后我想通过网络传输它们并进行分析。到目前为止,我在python中做了如下工作:

#run a bunch of queries before hand with the results in remote files

....
counter = 0
mergedDataFrame = None
while NotDone:
  output = subprocess.check_output('ssh blah@blah cat /data/file%08d'%(counter))
  data = pandas.read_csv(...)
  #do lots of analysis, append, merge, numpy stuff etc...
  mergedDataFrame = pandas.merge(...)
  counter += 1

在某个时刻,我在check_output命令中收到以下错误:[Errno 12]无法分配内存

背景

多亏了下面的问题,我想我知道出了什么问题。发布了许多解决方案,我正在尝试确定哪些解决方案将避免[Errno 12]无法使用fork/clone分配与子流程实现相关联的内存错误。

Python subprocess.Popen "OSError: [Errno 12] Cannot allocate memory"这给出了底层诊断,并建议了一些解决方法,如生成单独的脚本等。。。

Understanding Python fork and memory allocation errors建议使用rfoo来规避fork/clone的子进程限制,生成子进程和复制内存等。。。这似乎意味着客户机-服务器模型

What is the simplest way to SSH using Python?,但是由于内存限制和fork/clone实现,我有额外的约束不能使用subprocess?解决方案建议使用paramiko或在其上构建的东西,其他人建议使用子流程(我发现在我的情况下,子流程不起作用)。

还有其他类似的问题,但答案经常提到文件描述符是罪魁祸首(在本例中,它们不是罪魁祸首)、向系统添加更多RAM(我不能这样做)、升级到x64(我已经在x64上了)。一些关于以诺门问题的暗示。一些回答提到试图确定subprocess.Popen(在我的例子中是check_output)是否没有正确地清理进程,但是看起来S.Lott和其他人同意子进程代码本身正在正确地清理。

我已经搜索了githubhttps://github.com/paramiko/paramiko/search?q=Popen&type=Code上的源代码,它似乎在proxy.py文件中使用了subprocess。

实际问题

这是否意味着最终paramiko使用的是上面描述的Popen解决方案,当python内存占用增加并且由于clone/fork实现而重复进行Popen调用时会出现问题?

如果paramiko不工作,有没有其他的方法来做我正在寻找的只有客户端的解决方案?还是需要客户机/服务器/套接字解决方案?如果是这样的话,rfoo、tornado或zeromq、http传输会在这里工作吗?

注释 我运行64位linux 8GB主内存。我不想追求购买更多内存的选择。


Tags: 内存paramikooutputclonecheckfork解决方案建议
3条回答

如果内存不足,可能需要增加交换内存。或者您可能根本没有启用交换。在Ubuntu中(它也应该适用于其他发行版),您可以通过以下方式检查交换:

$sudo swapon -s

如果为空,则表示您没有启用任何交换。要添加1GB交换:

$sudo dd if=/dev/zero of=/swapfile bs=1024 count=1024k
$sudo mkswap /swapfile
$sudo swapon /swapfile

将以下行添加到fstab以使交换永久。

$sudo vim /etc/fstab

     /swapfile       none    swap    sw      0       0 

可以找到源和更多信息here

如果内存不足,可能是因为子进程试图同时读取太多内存。除了使用重定向到本地文件之外,解决方案可能是将类似popen的功能与stdin/stdout对一起使用,stdin/stdout对可以一次读取一点。

这应该做到:

http://docs.python.org/3.3/library/subprocess.html#replacing-os-popen-os-popen2-os-popen3

这样,你可以阅读行或块,而不是整个事情一次。

相关问题 更多 >