我不知道如何解决这个问题:
Traceback(最近一次调用最后一次):文件 " /usr/local/cabinet_dev/cabinet/lib/python3.4/site-packages/eventlet/hubs/hub.py" ;, 第458行,在fire_timers中 timer()File" /usr/local/cabinet_dev/cabinet/lib/python3.4/site-packages/eventlet/hubs/timer.py", 第58行,致电 cb(* args,** kw)File" /usr/local/cabinet_dev/cabinet/lib/python3.4/site-packages/eventlet/greenthread.py", 第218行,主要 result = function(* args,** kwargs)文件" ./ monitor.py",第148行,在caughtBridge中 对于self.active.keys()中的调用:RuntimeError:迭代期间字典改变了大小
在下面的代码中:
def caughtBridge(self):
while True:
event = self.bridgeQueue.get()
uniqueid1 = str(event.headers.get('Uniqueid1'))
uniqueid2 = str(event.headers.get('Uniqueid2'))
for call in self.active.keys():
if self.active[call]['uniqueid'] == uniqueid1:
self.active[call]['uniqueid2'] = uniqueid2
if self.active[call]['uniqueid'] == uniqueid1:
for listener in self.listeners:
for number in listener.getNumbers():
if number == self.active[call]['exten']:
if not self.active[call]['answered']:
self.sendEvent({"status": "bridge", "id": self.active[call]['uniqueid'],
"number": self.active[call]['exten']},
listener.getRoom())
self.__callInfo(self.active[call], listener.getRoom())
self.active[call]['answered'] = True
self.bridgeQueue.task_done()
答案 0 :(得分:2)
使用self.active.keys()
的副本,例如:
for call in list(self.active.keys()):
未检测到添加或删除 dict
条目?
如果添加,其他线程将看不到添加的dict
条目。
如果删除,当前线程将因 键错误 而失败,
你必须抓住这些。
例如:
for call in list(self.active.keys()):
<Lock that call to prevent removing>
if call in self.active:
...
self.active[call]['answered'] = True
else:
# call removed do nothing
<Unlocked that call to do whatever in other Thread>
self.bridgeQueue.task_done()
阅读Python»3.6.2文档:threading.html#lock-objects
基本实现配对方法self.lock(call)
和self.unlock(call)
,例如:
未经测试的代码:
要防止死锁,您必须保证会self.unlock(call)
到达!class xxx def __init__.... self_lock = threading.Lock # Init all self.active[call]['lock'] = False def lock(self, call): # self._lock ist class threading.Lock # self._lock has to be the same for all Threads with self._lock: if call in self.active and not self.active[call]['lock']: self.active[call]['lock'] = True return True else: return False def unlock(self, call): with self._lock: self.active[call]['lock'] = False # Usage: for call in list(self.active.keys()): if self.lock(call): ... self.active[call]['answered'] = True self.unlock(call) else: # call removed do nothing self.bridgeQueue.task_done()