我有一个运行循环的python脚本。在此循环中,函数DoDebugInfo
被调用,每次循环迭代一次。此功能基本上使用matplotlib将一些图片打印到硬盘,导出KML文件并进行其他一些计算,不返回任何内容。
我遇到的问题是python,对于每次运行,函数DoDebugInfo
会占用越来越多的RAM。我猜一些变量正在增加每个循环的大小。
我在通话前后添加了以下几行:
print '=== before: ' + str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000)
DoDebugInfo(inputs)
print '=== after: ' + str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000)
输出结果为:
=== before: 71598.08
=== after: 170237.952
=== before: 170237.952
=== after: 255696.896
=== before: 255696.896
=== after: 341409.792
正如您所看到的,在调用之前程序具有内存占用,并且在调用之后它会增加,但在下一次调用之前保持稳定。
这是为什么?因为DoDebugInfo(inputs)
是一个不返回任何内容的函数,所以某些变量如何保留在内存中呢?是否需要清除函数末尾的所有变量?
编辑:
DoDebugInfo
导入此功能:
def plot_line(x,y,kind,lab_x,lab_y,filename):
fig = plt.figure(figsize=(11,6),dpi=300)
ax = fig.add_subplot(111)
ax.grid(True,which='both')
#print 'plotting'
if type(x[0]) is datetime.datetime:
#print 'datetime detected'
ax.plot_date(matplotlib.dates.date2num(x),y,kind)
ax.fmt_xdata = DateFormatter('%H')
ax.autoscale_view()
fig.autofmt_xdate()
else:
#print 'no datetime'
ax.plot(x,y,kind)
xlabel = ax.set_xlabel(lab_x)
ax.set_ylabel(lab_y)
fig.savefig(filename,bbox_extra_artists=[xlabel], bbox_inches='tight')
def plot_hist(x,Nbins,lab_x,lab_y,filename):
fig = plt.figure(figsize=(11,6),dpi=300)
ax = fig.add_subplot(111)
ax.grid(True,which='both')
ax.hist(x,Nbins)
xlabel = ax.set_xlabel(lab_x)
ax.set_ylabel(lab_y)
fig.savefig(filename,bbox_extra_artists=[xlabel], bbox_inches='tight')
并使用以下内容将10个数字绘制到磁盘上:
plot_line(index,alt,'-','Drive Index','Altitude in m',output_dir + 'name.png')
如果我评论使用plot_line
的行没有发生问题,那么泄漏应该在这行代码上。
由于
答案 0 :(得分:5)
问题依赖于创建和永不关闭的数字。不知何故python让他们都活着。
我添加了
行plt.close()
到我的每个情节函数plot_line
和plot_hist
,问题就消失了。
答案 1 :(得分:0)
尺寸是否无限制地增长?很少有程序(或库)将堆返回到它们分配的系统,即使不再使用它们,CPython(2.7.3)也不例外。通常的罪魁祸首是malloc
,它将根据需要增加进程内存,在free
时将空间返回到其空闲列表,但永远不会从系统中取消分配它所请求的内容。此示例代码故意抓取内存并显示进程使用是有界的和有限的:
import resource
def maxrss(start, end, step=1):
"""allocate ever larger strings and show the process rss"""
for exp in range(start, end, step):
s = '0' * (2 ** exp)
print '%5i: %sk' % (exp,
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000)
# s goes out of scope here and is freed by Python but not returned
# to the system
try:
maxrss(1, 40, 5)
except MemoryError:
print 'MemoryError'
maxrss(1, 30, 5)
输出(在我的机器上)的部分:
26: 72k
31: 2167k
MemoryError
1: 2167k
6: 2167k
...
26: 2170k
这表明解释器无法从系统获得2 ** 36个字节的堆,但仍然有“现有”内存来填充以后的请求。正如脚本的最后一行所示,内存可供Python使用,即使它当前没有使用它。