簡體   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