I wrote a function that plots a figure consisting of two subplots of different sizes:
def draw_plot(data, function, sigma_value):
gs = gridspec.GridSpec(1, 5)
ax1 = subplot(gs[0, 0:3])
ax2 = subplot(gs[0, 3:5], sharey=ax1)
gs.update(wspace=0.05)
...
I should mention that this is a module-level function, so at the top of that module I make imports
from pylab import *
import matplotlib.gridspec as gridspec
When I run myplot.draw_plot(...)
, I get RuntimeError
. The thing is this behaviour is inconsistent. I can call the function, say, three times, and the first two times I get the error, whereas the third time it runs OK.
The Traceback is
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
File "myplot.py", line 105, in draw_plot
ax1 = subplot(gs[0, 0:3])
File "C:\Python32\lib\site-packages\matplotlib\pyplot.py", line 766, in subplot
a = fig.add_subplot(*args, **kwargs)
File "C:\Python32\lib\site-packages\matplotlib\figure.py", line 779, in add_subplot
a = subplot_class_factory(projection_class)(self, *args, **kwargs)
File "C:\Python32\lib\site-packages\matplotlib\axes.py", line 8380, in __init__
self._axes_class.__init__(self, fig, self.figbox, **kwargs)
File "C:\Python32\lib\site-packages\matplotlib\axes.py", line 467, in __init__
self.cla()
File "C:\Python32\lib\site-packages\matplotlib\axes.py", line 910, in cla
self._shared_y_axes.clean()
File "C:\Python32\lib\site-packages\matplotlib\cbook.py", line 1493, in clean
for key, val in mapping.items():
RuntimeError: dictionary changed size during iteration
Thanks for any help!
EDIT
Obviously I've been trying to figure out myself what is going on, so following the Traceback
I checked the clean()
function in cbook.py
.
def clean(self):
"""
Clean dead weak references from the dictionary
"""
mapping = self._mapping
for key, val in mapping.items():
if key() is None:
del mapping[key]
val.remove(key)
In the function I added a line that would print mapping.items()
and I noticed that the error occurs when there are entries similar to <weakref at 0480EBA0; dead>
among those items. I'm totally unfamiliar with weak references so I'm stuck again.
EDIT 2
It's certainly not a good solution but commenting out the clean()
function body helps in my case without producing any new errors.
I've just found a very recent post Safely iterating over WeakKeyDictionary and WeakValueDictionary that helps with a very similar issue.
So using answer given by Bakuriu I edited close()
function as following
def clean(self):
"""
Clean dead weak references from the dictionary
"""
mapping = self._mapping
for key, val in list(mapping.items()): # iterate over list now
if key() is None:
del mapping[key]
val.remove(key)
and it seems to be working just fine!
EDIT
I've just found out that in a new version of matplotlib
the function looks like this:
def clean(self):
"""
Clean dead weak references from the dictionary
"""
mapping = self._mapping
to_drop = [key for key in mapping if key() is None]
for key in to_drop:
val = mapping.pop(key)
val.remove(key)
Source:
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/cbook.py
Just a short explanation of what is happening:
You looped over an iterable (list, dict, whatever) like this:
for somevalue in someiterable:
#do something
And inside the loop you tried to structurally modify the iterable, meaning you added or removed values. This is not allowed because it would mess with the for loop. The solution to this is usually to iterate over a copy of the iterable, leaving you free to altering the original.
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