gpt4 book ai didi

python - logger.removeHandler(logger.handlers[0]) 如何抛出 ValueError : list. 删除(x) : x not in list?

转载 作者:太空宇宙 更新时间:2023-11-03 14:46:21 24 4
gpt4 key购买 nike

我正在尝试调试别人的 Python 代码中的异常,但我不是 Python 专家。该代码尝试刷新并删除标准 Python 记录器上的所有处理程序:

def restart_logging(logger_id):
logger = logging.getLogger(logger_id)
while logger.handlers:
handler = logger.handlers[0]
handler.flush()
logger.removeHandler(handler)
init_logging(logger_id)

这会引发异常:

File "/usr/lib64/python2.6/logging/__init__.py", line 1208, in removeHandler
self.handlers.remove(hdlr)
ValueError: list.remove(x): x not in list

我已经查看了 StackOverflow 的其他“x 不在列表中”问题,它们都属于这两类:

  • 多次删除同一项目(通常是因为执行 for x in list: list.remove(x) 而不是 while list: list.remove(list[0]) )
  • 删除列表中从未出现过的项目

我不明白这两者在这里如何适用。

首先,使用 while 循环:当仍然有处理程序时,获取第一个处理程序(成功,否则会出现 IndexError),刷新它,删除它。即使删除了列表中的多个条目,这也是一个 while 循环测试列表是否仍然有条目,而不是迭代(可能删除)对象的 for 循环。

查看logging模块源代码,它只调用remove()一次,甚至检查处理程序是否在调用remove()之前的列表:

def removeHandler(self, hdlr):
"""
Remove the specified handler from this logger.
"""
if hdlr in self.handlers:
#hdlr.close()
hdlr.acquire()
try:
self.handlers.remove(hdlr)
finally:
hdlr.release()

此代码作为 Django Web 应用程序的一部分执行。我可以理解,例如,如果它是一个 Java J2EE 应用程序,其中两个线程可以同时访问同一个列表,并且没有锁来使“获取第一项并删除它”成为原子操作,因此两个线程都会看到相同的内容列表中的元素,但只有一个会删除它,另一个会失败,因为线程删除了第一个线程的“此项目是否在列表中”和“从列表中删除此项目”之间的元素。

但是,据我了解,Python 没有并发性,并且使用全局解释器锁来阻止同时发生多件事情。所以这应该是不可能的。

所以,我无法弄清楚为什么 list.remove(x): x not in list 在这里发生,而且我无法制作一个可靠发生的测试用例。我可以做些什么来进一步理解这个问题?

最佳答案

虽然单个操作可能是原子的(以及您可能已经注意到的 list.remove 等操作,但这只是由于 CPython 的实现细节而造成的), removeHandler当然不是。在 Python 2.6 实现中(您已经发布了非常有帮助的内容),上下文切换可以在 if 之后发生。语句和锁获取之前(假设这就是 hdlr.acquire() 所做的)。因此,如果两个线程同时调用此函数,则当一个线程随后释放其对 GIL 的持有而另一个线程运行整个过程直至完成时,肯定会引发异常(原始线程将从 if、处理程序内部继续)仍然指向原始的,它将获取 IO 锁,然后尝试将其从列表中删除,从而导致不必要的异常)。

在 Python 2.7 中,此问题已得到修复,removeHandler方法改为:

    def removeHandler(self, hdlr):
"""
Remove the specified handler from this logger.
"""
_acquireLock()
try:
if hdlr in self.handlers:
self.handlers.remove(hdlr)
finally:
_releaseLock()

请注意现在如何在 if 语句之前获取锁。

关于python - logger.removeHandler(logger.handlers[0]) 如何抛出 ValueError : list. 删除(x) : x not in list?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46217752/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com