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

Python 如何避免使用子流程模块导致[Errno 12]无法分配内存错误,python,networking,memory,subprocess,paramiko,Python,Networking,Memory,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

完成工作测试用例

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

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]无法分配内存

背景

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

这给出了潜在的诊断,并提出了一些解决方法,如生成单独的脚本等

建议使用rfoo绕过fork/clone和派生子进程以及复制内存等子进程限制。。。这似乎意味着客户机-服务器模型

,但由于内存限制和fork/clone实现,我还有一些额外的限制,无法使用子流程?解决方案建议使用paramiko或构建在它之上的东西,其他人则建议使用subprocess(我发现在我的情况下,它不起作用)

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

我在github上搜索了源代码,它似乎在proxy.py文件中使用了subprocess

实际问题

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

如果paramiko无法工作,是否有其他方法可以实现我所寻求的仅客户端解决方案?还是需要客户机/服务器/套接字解决方案?如果是这样的话,rfoo、tornado或zeromq、http传输中的任何一种都能在这里工作吗

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

这应该可以做到:


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

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

如果内存不足,可能需要增加交换内存。或者您可能根本没有启用交换。在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 

可以找到源代码和更多信息。

我不确定是否遗漏了什么,但我不想替换os.popen,我已经在使用子流程。问题不在于实际的文件大小,而在于子进程中的fork/clone否,这不是因为子进程读取了太多内存。这些文件只有200-300MB。请阅读张贴的链接,特别是第一个链接,以查看问题。它与子流程的实现方式有关:fork/clone。Linux fork/clone是写时复制。它不应该使用大量实际内存,除非您的交换策略不允许过度使用。对于CPython来说,最主要的美中不足之处在于,CPython的引用计数分散在各个地方,这会很快使页面变脏,需要进行复制。如果您能提供适当的输入和预期的输出,我将有兴趣更深入地研究这个问题。我尝试了:output=subprocess。检查_output(['ssh','localhost','cat','/etc/services']),但它没有复制问题。您使用的是什么操作系统?您使用的是什么版本的Python?如果您使用的是Linux,那么您的过度使用策略是什么?1.我可以用计算机重现这个问题。(64位linux)2。通常我希望paramiko使用套接字来创建连接。你试过了吗?我确实看到了链接,谢谢。他们似乎大多建议帕拉米科。Paramiko(通过套接字)应绕过子流程模块分叉/克隆问题,正确吗?我对paramiko的主要担忧(可能是错误的)是,我进行了一次快速的源代码搜索,发现它使用了子流程模块——尽管我不知道它的用途和程度。paramiko是一个本机python ssh实现。它不为传输的任何部分使用子流程。相关:感谢您的建议。我试着检查交换大小,它是10GB交换空间启用的。这给了我一个想法,我发现我的磁盘空间没有可用空间。