7

我写了一个函数来绘制一个由两个不同大小的子图组成的图形:

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)
    ...

我应该提到这是一个模块级函数,所以在该模块的顶部我进行导入

from pylab import *
import matplotlib.gridspec as gridspec

当我跑步时myplot.draw_plot(...),我得到了RuntimeError。问题是这种行为是不一致的。我可以调用该函数,例如三次,前两次我得到错误,而第三次运行正常。

追溯是

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

谢谢你的帮助!

编辑

显然我一直在试图弄清楚自己发生了什么,所以按照Traceback我检查clean()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)

在函数中,我添加了一行可以打印的内容mapping.items(),我注意到当<weakref at 0480EBA0; dead>这些项目中有类似的条目时会发生错误。我对弱引用完全不熟悉,所以我又被困住了。

编辑 2 这当然不是一个好的解决方案,但在我的情况下注释掉clean()函数体会有所帮助,而不会产生任何新的错误。

4

2 回答 2

3

我刚刚发现了一篇最近发布的安全迭代 WeakKeyDictionary 和 WeakValueDictionary的帖子,它有助于解决一个非常相似的问题。

因此,使用 Bakuriu 给出的答案,我编辑close()了以下功能

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)

它似乎工作得很好!

编辑

我刚刚发现在新版本matplotlib的函数中看起来像这样:

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)

来源:

https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/cbook.py

于 2012-09-14T18:23:23.107 回答
1

只是对正在发生的事情的简短解释:

您像这样循环遍历一个可迭代的(列表、字典等):

for somevalue in someiterable:
    #do something

在循环内部,您尝试在结构上修改可迭代对象,这意味着您添加或删除了值。这是不允许的,因为它会弄乱 for 循环。对此的解决方案通常是迭代可迭代的副本,让您可以自由地更改原始文件。

于 2012-09-14T18:24:40.873 回答