繁体   English   中英

如何解决这个python错误? RuntimeError:字典在迭代期间改变了大小

[英]How to fix this python error? RuntimeError: dictionary changed size during iteration

它给了我这个错误:

Exception in thread Thread-163:
Traceback (most recent call last):
  File "C:\Python26\lib\threading.py", line 532, in __bootstrap_inner
    self.run()
  File "C:\Python26\lib\threading.py", line 736, in run
    self.function(*self.args, **self.kwargs)
  File "C:\Users\Public\SoundLog\Code\Código Python\SoundLog\SoundLog.py", line 337, in getInfo
    self.data1 = copy.deepcopy(Auxiliar.DataCollection.getInfo(1))
  File "C:\Python26\lib\copy.py", line 162, in deepcopy
    y = copier(x, memo)
  File "C:\Python26\lib\copy.py", line 254, in _deepcopy_dict
    for key, value in x.iteritems():
RuntimeError: dictionary changed size during iteration

在执行我的python程序时。

我怎样才能避免这种情况发生?

提前致谢 ;)

根据其他答案,正常的建议是避免使用iteritems (改为使用items )。 那当然不是你的选择,因为iteritems调用是在你的系统调用的深处代表你完成的。

因此,我建议,假设Auxiliar.DataCollection.getInfo(1)返回一个字典(在复制期间正在更改的字典)是您将deepcopy调用更改为:

self.data1 = copy.deepcopy(dict(Auxiliar.DataCollection.getInfo(1)))

这需要有问题的dict的“快照”,快照不会改变,所以你会没事的。

如果Auxiliar.DataCollection.getInfo(1) 没有返回dict,但是一些更复杂的对象(包括dicts作为项和/或属性),它会更复杂一些,因为那些dicts是你需要快照的。 但是,在这种情况下,不可能更具体,因为你完全不知道组成关键Auxiliar.DataCollection.getInfo(1)调用的代码! - )

虽然这个线程已有近2年的历史,但我遇到了类似的问题:

我有一个基于Queue模块的生产者/消费者类系统。 我的工人类'run-method定义如下:

def run(self):
    while True:
    a, b, c = Worker._Queue.get()
    # do some stuff
    ...
    self.notify() # notify observers
    Worker._Queue.task_done()

main-class定义了一个update-method,用于通知工作者收集数据并将其存储在字典中。 由于多个线程可能会更改主类中的字典,因此此“关键部分”将被锁定

def update(self, worker):
    Main.indexUpdateLock.acquire()
    # get results of worker
    index = worker.getIndex()
    # copy workers index into the main index
    try:
        for i in index:
            if i in self._index:
                self._index[i] += index[i]
            else:
                self._index[i] = index[i]
    finally:
        # index copied - release the lock
        Main.indexUpdateLock.release()

现在这在大多数情况下都有效 - 但是在某些情况下,有时'对于i in index:'在Main的update-method中抛出一个RuntimeError:字典在迭代期间改变了大小。 indexUpdateLock定义为threading.Lock()或threading.RLock() - 行为不会改变我定义它的方式。

对于我在dict(索引):确实解决了问题,但由于索引可能包含几千个条目,复制它并没有真正提高性能imo - 这就是我试图直接复制这些值的原因。

虽然更新是在Main中定义的,但是通过在worker的线程中调用notify(),更新也应该在worker的线程中执行,因此task_done()只有在notify()或更高版本的update()完成处理时才会执行。 通过临界区的定义,一次只允许一个线程执行该区域 - 或者我在这里有一些逻辑错误? 我真的没有看到工作者索引的更改来自哪里,因为唯一的索引访问权限是在Main.update()和Worker中,但是直到task_done()没有执行,没有其他方法修改工作者内部的索引


编辑:确定,修复了由发送一个额外条目的工作者内部的HTMLParser引起的问题,尽管源已经关闭 - 虽然奇怪的行为。 虽然对于索引中的i:仍然在index.keys()中为i生成错误:没有,所以我会坚持这一点

听起来你正在尝试迭代的字典中添加或删除某些内容。 大多数语言都不允许这样做。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM