[英]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.