完整的工作测试案例
当然,根据您在本地和远程计算机上的内存,您的阵列大小会有所不同。
z1 = numpy.random.rand(300000000,2);
for i in range(1000):
print('*******************************************
');
direct_output = subprocess.check_output('ssh blah@blah"ls /"', shell=True);
direct_output = 'a'*1200000;
a2 = direct_output*10;
print(len(direct_output));
当前用例
如果它有助于我的用例如下:
我发出数据库查询,然后将结果表存储在远程计算机上。然后我想通过网络传输它们并进行分析。到目前为止,我在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]无法分配内存"这给出了基础诊断并提出了一些解决方法,如产生单独的脚本等...
了解Python fork和内存分配错误建议使用rfoo来规避fork / clone的子进程限制并生成子进程和复制内存等...这似乎意味着客户端 - 服务器模型
使用Python进行SSH的最简单方法是什么? ,但由于内存限制和fork / clone实现,我有额外的约束,我不能使用子进程?解决方案建议使用paramiko或基于它构建的东西,其他建议使用subprocess(我发现它不适用于我的情况)。
还有其他类似的问题,但答案经常谈到文件描述符是罪魁祸首(在这种情况下,他们不是),向系统添加更多的RAM(我不能这样做),升级到x64(我已经在x64上)。一些暗示ENOMEM的问题。一些答案提到尝试确定subprocess.Popen(在我的情况下是check_output)是否没有正确清理进程,但它看起来像S. Lott和其他人同意子进程代码本身正在清理。
使用subprocess.Popen的Python内存分配错误
Python IOError虽然有很多,但无法分配内存
无法在Popen命令上分配内存
Python subprocess.Popen错误与OSError:[Errno 12]一段时间后无法分配内存
我搜索了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主内存。我不想追求购买更多内存的选择。
我可以用更简单的例子重现这个问题。 (64位linux)2。通常我希望paramiko使用套接字来创建连接。
你有没有尝试过如何在python scp?
我确实看到了链接,谢谢你。他们似乎主要建议paramiko。 Paramiko(通过套接字)应该绕过子进程模块fork / clone问题是否正确?我对paramiko的主要关注(可能是错误的)是我做了一个快速的源代码搜索并看到它使用了子进程模块 - 虽然我不知道是什么用于什么程度。
关于源代码示例。是的,您的简化版本也会导致错误。我想把ssh放在示例中,因为我认为在我的情况下,我机器上的内存可能不是主要问题,就好像我在本地执行check_output或其他命令一样,我没有快速地遇到内存错误。但是,可能是我的本地盒子有更多的可用内存,因此我没有尽快看到问题但是如果我调整阵列大小那么。
Paramiko是一个原生的python ssh实现。它不对传输的任何部分使用子进程。
谢谢JimB的评论。我将继续推进paramiko!
相关:Python subprocess.Popen"OSError:[Errno 12无法分配内存"
如果内存不足,可能需要增加交换内存。或者您可能根本没有启用交换。在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
可以在此处找到来源和更多信息。
谢谢你的建议。我尝试检查交换大小,并启用了10GB的交换空间。
这给了我一个想法,我发现我的磁盘空间没有可用空间。
如果你的内存不足,可能是因为子进程试图同时读入太多内存。除了使用重定向到本地文件之外,解决方案可能是使用类似popen的功能,并且stdin / stdout对可以一次读取一点。
不,不是因为子进程读取太多内存。文件只有200-300MB。请阅读发布的链接,尤其是第一个链接,以查看问题。它与子进程的实现方式有关:fork / clone。 stackoverflow.com/questions/1367373/
Linux fork / clone是写入时的副本。它不应该使用大量的实际内存,除非您的交换策略不允许过度使用。对于CPython来说,美中不足的主要原因是CPython的参考计数遍布整个地方,这很快会使页面变脏并需要复制。
如果你想出一个带有适当输入和预期输出的sscce.org,我有兴趣更深入地研究这个问题。我试过:output = subprocess.check_output(['ssh','localhost','cat','/ etc / services']),但它没有复制问题。
你在用什么操作系统?您使用的是哪个版本的Python?
如果您使用的是Linux,那么您的过度使用策略是什么? github.com/torvalds/linux/blob/master/Documentation/sysctl/
你有多少身体素质?你有多少交换空间?
Physmem是8GB,交换是10GB。我正在运行CentOS 6.4,64位。 Python版本是2.7.3 x64。不确定如何检查overcommit,但查看/ proc / sys / vm:memory_failure_recovery:empty nr_overcommit_hugepages:empty overcommit_memory:empty overcommit_ratio:empty
很难得到一个最小的工作示例,但我正在努力。同时了解paramiko是否为对象的整个生命周期打开一个子进程,或者如果它为每个远程命令运行打开一个单独的子进程是我最大的问题。
让我们在聊天中继续讨论
"cat / proc / sys / vm / overcommit_memory"应告诉我们您的过度使用政策。
我试着开始聊天。加入这里:chat.stackoverflow.com/rooms/41642/。我开始确定发生了什么。这是一个最小的例子:z1 = numpy.random.rand(300000000,2);对于范围内的i(1000):a1 = subprocess.check_output('ssh blah @ blah"ls / home /"');#任何远程命令都会执行#a1 ='a'* 1200000; a2 = a1 * 10#在再次创建更多内存循环到远程检查输出后,远程机器返回ENOMEM错误。所以它是远程机器的罪魁祸首。仍然不得不绕过这个?帕拉米科会解决这个问题
这应该这样做:
http://docs.python.org/3.3/library/subprocess.html#replacing-os-popen-os-popen2-os-popen3
这样,您可以一次读取行或块,而不是整个行。
我不确定我是否遗漏了什么,但我不想替换os.popen,我已经在使用子进程了。实际文件大小不是问题,而是在子进程中使用fork / clone