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

Pau*_*aul 37 python memory networking subprocess paramiko

完整的工作测试案例

当然,根据您在本地和远程计算机上的内存,您的阵列大小会有所不同.

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));
Run Code Online (Sandbox Code Playgroud)

当前用例

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

我发出数据库查询,然后将结果表存储在远程计算机上.然后我想通过网络传输它们并进行分析.到目前为止,我在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
Run Code Online (Sandbox Code Playgroud)

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

背景

感谢以下问题,我想我已经知道出了什么问题.发布了许多解决方案,我试图确定哪些解决方案将避免[Errno 12]无法使用fork/clone分配与子进程实现相关的内存错误.

Python subprocess.Popen"OSError:[Errno 12]无法分配内存" 这给出了基础诊断并提出了一些解决方法,如产生单独的脚本等...

了解Python fork和内存分配错误 建议使用rfoo来规避fork/clone的子进程限制并生成子进程和复制内存等...这似乎意味着客户端 - 服务器模型

使用Python进行SSH的最简单方法是什么? ,但由于内存限制和fork/clone实现,我有额外的约束,我不能使用子进程?解决方案建议使用paramiko或基于它构建的东西,其他建议使用subprocess(我发现它不适用于我的情况).

还有其他类似的问题,但答案经常谈到文件描述符是罪魁祸首(在这种情况下,他们不是),向系统添加更多的RAM(我不能这样做),升级到x64(我已经在x64上).一些暗示ENOMEM的问题.一些答案提到尝试确定subprocess.Popen(在我的情况下是check_output)是否没有正确清理进程,但它看起来像S. Lott和其他人同意子进程代码本身正在清理.

我搜索了github上的源代码https://github.com/paramiko/paramiko/search?q=Popen&type=Code,它似乎在proxy.py文件中使用了子进程.

实际问题

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

如果paramiko不起作用是否有另一种方法来做我正在寻找的客户端唯一的解决方案?或者是否需要客户端/服务器/套接字解决方案?如果是rfoo,tornado或zeromq中的任何一个,http转移在这里工作?

注意 我正在运行64位linux 8GB主内存.我不想追求购买更多内存的选择.

Nim*_*ima 54

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

$sudo swapon -s
Run Code Online (Sandbox Code Playgroud)

如果它是空的,则表示您没有启用任何交换.要添加1GB交换:

$sudo dd if=/dev/zero of=/swapfile bs=1024 count=1024k
$sudo mkswap /swapfile
$sudo swapon /swapfile
Run Code Online (Sandbox Code Playgroud)

添加以下行以fstab使交换永久化.

$sudo vim /etc/fstab

     /swapfile       none    swap    sw      0       0 
Run Code Online (Sandbox Code Playgroud)

可以在此处找到来源和更多信息.


dst*_*erg 0

这应该可以做到:

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

这样,您可以读取行或块,而不是一次读取整个内容。

  • 我不确定我是否遗漏了一些东西,但我不想替换 os.popen,我已经在使用子进程了。问题不是实际的文件大小,而是子进程中的分叉/克隆 (2认同)

归档时间:

查看次数:

63463 次

最近记录:

11 年,6 月 前