Skip to content

Commit 2336fb3

Browse files
committed
Fix plotting memory leak and add regression test
1 parent 67b08f6 commit 2336fb3

File tree

3 files changed

+185
-118
lines changed

3 files changed

+185
-118
lines changed

doc/source/whatsnew/v0.16.1.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ Bug Fixes
141141

142142

143143

144-
145144
- Bug in unequal comparisons between categorical data and a scalar, which was not in the categories (e.g. ``Series(Categorical(list("abc"), ordered=True)) > "d"``. This returned ``False`` for all elements, but now raises a ``TypeError``. Equality comparisons also now return ``False`` for ``==`` and ``True`` for ``!=``. (:issue:`9848`)
146145
- Bug in DataFrame ``__setitem__`` when right hand side is a dictionary (:issue:`9874`)
147146
- Bug in ``where`` when dtype is ``datetime64/timedelta64``, but dtype of other is not (:issue:`9804`)
@@ -164,3 +163,4 @@ Bug Fixes
164163

165164
- Fixed latex output for multi-indexed dataframes (:issue:`9778`)
166165
- Bug causing an exception when setting an empty range using ``DataFrame.loc`` (:issue:`9596`)
166+
- Fixed memory leak in ``AreaPlot`` and ``LinePlot`` that prevented calls to ``plt.close()`` from having any effect. (:issue:`9003`)

pandas/tests/test_graphics.py

+29
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
from numpy.testing import assert_array_equal, assert_allclose
2929
from numpy.testing.decorators import slow
3030
import pandas.tools.plotting as plotting
31+
import weakref
32+
import gc
3133

3234

3335
def _skip_if_mpl_14_or_dev_boxplot():
@@ -3390,6 +3392,33 @@ def test_sharey_and_ax(self):
33903392
"y label is invisible but shouldn't")
33913393

33923394

3395+
def test_memory_leak(self):
3396+
""" Check that every plot type gets properly collected. """
3397+
import matplotlib.pyplot as plt
3398+
results = {}
3399+
for kind in plotting._plot_klass.keys():
3400+
args = {}
3401+
if kind in ['hexbin', 'scatter', 'pie']:
3402+
df = self.hexbin_df
3403+
args = {'x': 'A', 'y': 'B'}
3404+
elif kind == 'area':
3405+
df = self.tdf.abs()
3406+
else:
3407+
df = self.tdf
3408+
3409+
# Use a weakref so we can see if the object gets collected without
3410+
# also preventing it from being collected
3411+
results[kind] = weakref.proxy(df.plot(kind=kind, **args))
3412+
3413+
# have matplotlib delete all the figures
3414+
plt.close('all')
3415+
# force a garbage collection
3416+
gc.collect()
3417+
for key in results:
3418+
# check that every plot was collected
3419+
with tm.assertRaises(ReferenceError):
3420+
# need to actually access something to get an error
3421+
results[key].lines
33933422

33943423
@tm.mplskip
33953424
class TestDataFrameGroupByPlots(TestPlotBase):

0 commit comments

Comments
 (0)