阅读 http://bugs.python.org/msg160297 ,我可以看到 Stephen White 编写的一个简单脚本,它演示了 python 线程如何因这个异常而出错
Exception AttributeError: AttributeError("'_DummyThread' object has no attribute '_Thread__block'",) in <module 'threading'
鉴于 Stephen White 的源代码 (http://bugs.python.org/file25511/bad-thread.py),
import os
import thread
import threading
import time
def t():
threading.currentThread() # Populate threading._active with a DummyThread
time.sleep(3)
thread.start_new_thread(t, ())
time.sleep(1)
pid = os.fork()
if pid == 0:
os._exit(0)
os.waitpid(pid, 0)
我们如何重写它以解决此错误?
最佳答案
The bug发生是因为在外部线程上调用 threading.currentThread()
时 threading
API 创建的虚拟线程对象与 threading._after_fork 之间的不良交互
函数,在调用 os.fork()
后调用以清理资源。
要在不修改 Python 源代码的情况下解决该错误,使用 __stop
的空操作实现猴子补丁 threading._DummyThread
:
import threading
threading._DummyThread._Thread__stop = lambda x: 42
最好通过 Richard Oudkerk 在评论中缩小错误的原因。和 cooyeah .发生的情况如下:
threading
模块允许从不是由threading
API 调用创建的线程调用threading.currentThread()
。然后它返回一个“虚拟线程”实例,该实例支持非常有限的Thread
API 子集,但对于识别当前线程仍然有用。threading._DummyThread
是作为Thread
的子类实现的。Thread
实例通常包含一个内部可调用对象 (self.__block
),它保持对为该实例分配的操作系统级锁的引用。由于可能最终使用self.__block
的公共(public)Thread
方法都被_DummyThread
覆盖,_DummyThread
的构造函数通过删除self.__block
有意释放操作系统级锁。threading._after_fork
打破封装并在所有已注册线程(包括虚拟线程)上调用私有(private)Thread.__stop
方法,其中__stop
从来没有打算被调用。 (它们不是由 Python 启动的,因此它们的停止也不由 Python 管理。)由于虚拟线程不知道__stop
,它们从Thread
继承它,并且该实现愉快地访问_DummyThread
实例中不存在的私有(private)__block
属性。此访问最终导致错误。
该错误已在 2.7 分支中由 modifying Thread.__stop
not to break 修复当 __block
被删除时。 3.x 分支,其中 __stop
拼写为 _stop
并因此受到保护,由 overriding _DummyThread
's _stop
to do nothing 修复它.
关于python - 理解 python 线程错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13193278/