I have to plot and saveplot in a loop from 1 to 500 with different data but gives a memory leak due to Matplot lib. Has someone any idea on how to deal with that ?
Simple case here :
import sys
import gc
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import pandas as pd
pdindex = pd.date_range(start='01/01/2013', freq='15min', end='01/01/2019')
df = pd.DataFrame({'test':np.random.normal(0,1,len(pdindex))}, index=pdindex)
def memplot_plot(df, i):
df.test.plot()
plt.title('graph' + str(i))
plt.savefig(str(i) + '.png', dpi=144)
plt.close()
for i in range(1, 100):
print '*******************************'
print 'i : ' + str(i)
print len( gc.get_objects())
print sys.getsizeof(gc.get_objects())
memplot_plot(df, i)
gc.collect()
And the output is (memory error as of i=6):
*******************************
i : 1
74682
325680
*******************************
i : 2
290627
1190248
*******************************
i : 3
506420
2145012
*******************************
i : 4
721993
3054204
*******************************
i : 5
937566
3865524
*******************************
i : 6
1153139
4892352
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Anaconda\lib\site- packages\spyderlib\widgets\externalshell\sitecustomize.py", line 580, in runfile
execfile(filename, namespace)
File "C:/PERSO/script_backtesting.py", line 124, in <module>
memplot_plot(df, i)
File "C:/PERSO/script_backtesting.py", line 107, in memplot_plot
plt.savefig(str(i) + '.png', dpi=144)
File "C:\Anaconda\lib\site-packages\matplotlib\pyplot.py", line 576, in savefig
res = fig.savefig(*args, **kwargs)
File "C:\Anaconda\lib\site-packages\matplotlib\figure.py", line 1470, in savefig
self.canvas.print_figure(*args, **kwargs)
File "C:\Anaconda\lib\site-packages\matplotlib\backend_bases.py", line 2192, in print_figure
**kwargs)
File "C:\Anaconda\lib\site-packages\matplotlib\backends\backend_agg.py", line 513, in print_png
FigureCanvasAgg.draw(self)
File "C:\Anaconda\lib\site-packages\matplotlib\backends\backend_agg.py", line 461, in draw
self.figure.draw(self.renderer)
File "C:\Anaconda\lib\site-packages\matplotlib\artist.py", line 59, in draw_wrapper
draw(artist, renderer, *args, **kwargs)
File "C:\Anaconda\lib\site-packages\matplotlib\figure.py", line 1079, in draw
func(*args)
File "C:\Anaconda\lib\site-packages\matplotlib\artist.py", line 59, in draw_wrapper
draw(artist, renderer, *args, **kwargs)
File "C:\Anaconda\lib\site-packages\matplotlib\axes\_base.py", line 2092, in draw
a.draw(renderer)
File "C:\Anaconda\lib\site-packages\matplotlib\artist.py", line 59, in draw_wrapper
draw(artist, renderer, *args, **kwargs)
File "C:\Anaconda\lib\site-packages\matplotlib\axis.py", line 1103, in draw
ticks_to_draw = self._update_ticks(renderer)
File "C:\Anaconda\lib\site-packages\matplotlib\axis.py", line 957, in _update_ticks
tick_tups = [t for t in self.iter_ticks()]
File "C:\Anaconda\lib\site-packages\matplotlib\axis.py", line 903, in iter_ticks
self.major.formatter.set_locs(majorLocs)
File "C:\Anaconda\lib\site-packages\pandas\tseries\converter.py", line 982, in set_locs
self._set_default_format(vmin, vmax)
File "C:\Anaconda\lib\site-packages\pandas\tseries\converter.py", line 966, in _set_default_format
format = np.compress(info['maj'], info)
File "C:\Anaconda\lib\site-packages\numpy\core\fromnumeric.py", line 1563, in compress
return compress(condition, axis, out)
MemoryError
Graph of the memory for the computer from launch the script to breack and to kill the console.
The last, Agg, is a non-interactive backend that can only write to files. It is used on Linux, if Matplotlib cannot connect to either an X display or a Wayland display.
Of course you can. The typical example of a memory leak is if you build a cache that you never flush manually and that has no automatic eviction policy. Antoine P.
This is apparently a bug. In case this question sticks around, the following modifications to the code eliminated the memory leak on my machine:
import sys
import gc
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import pandas as pd
pdindex = pd.date_range(start='01/01/2013', freq='15min', end='01/01/2019')
df = pd.DataFrame({'test':np.linspace(0,1,len(pdindex))}, index=pdindex)
fig, ax = plt.subplots()
def memplot_plot(df, i, f, a):
a.plot(df.index, df.test)
a.set_title('graph' + str(i))
f.savefig(str(i) + '.png', dpi=144)
a.cla()
for i in range(1, 100):
print '*******************************'
print 'i : ' + str(i)
print len( gc.get_objects())
print sys.getsizeof(gc.get_objects())
memplot_plot(df, i, fig, ax)
gc.collect()
The output now looks like this:
...
*******************************
i : 13
83727
732816
*******************************
i : 14
83727
732816
*******************************
i : 15
83727
732816
...etc
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With