我有一个奇怪的问题,希望有人能解释一下。
我有一段复杂的代码,最初是一个充满脚本的目录,我决定将其重新编写成一个包。此代码更改似乎触发了一些奇怪的死锁出现。
下面是对问题的规范再现的尝试;从这个代码按预期运行的意义上说,它失败了。实际重现问题可能需要大量代码;但我终生无法想象上下文中的违规代码片段有什么不同。
import numpy as np
from scipy.sparse import csr_matrix
from threading import Thread
def dummy():
print 'this is printed'
I = np.eye(3)
print 'all is still fine'
csr_matrix(I)
print 'this is never printed; csr_matrix appears to be a trigger for deadlock'
print np.ones(4)
print 'same problem; somehow, printing ndarrays is no longer cool either'
thr = Thread(target=dummy)
thr.start()
也许文档中的这个简短评论是相关的?我不确定我是否完全理解这里所说的内容
http://docs.python.org/2/library/threading#importing-in-threaded-code
首先,除了在主模块中,导入不应产生产生新线程然后以任何方式等待该线程的副作用。如果衍生线程直接或间接尝试导入模块,则不遵守此限制可能会导致死锁。
一些上下文:我正在使用 python 2.7,numpy 1.8,我尝试从 mayavi/traitsui 线程中生成这个新线程(我不明白为什么它应该相关,并且在包结构之前工作正常,但是没问题)。此外,在我生成的线程中有一大堆 numpy/scipy 代码执行得非常好;它只是打印 ndarrays 并创建稀疏矩阵,到目前为止,这些矩阵已被证明是死锁的触发因素。
我怀疑与 mayavi 有一些奇怪的交互,因为关闭 mayavi 窗口会导致所有死锁线程再次开始运行。也许这些特定的语句会触发 python 线程退让给 mayavi 线程,但它们无法再次获得焦点?
非常感谢能进一步缩小这个谜团的任何提示!
最佳答案
从您的评论来看,您似乎在您的一个子模块的顶层启动了 UI 事件循环。这不是一个好主意,因为它会导致与文档中提到的问题完全相同的问题。 import foo
不应该启动 UI 事件循环。问题是主线程抢了导入锁来处理模块的导入。此模块在完成导入之前启动 UI 事件循环。这与等待其他线程完成的情况基本相同;您正在等待 UI 循环完成。如果您的 UI 启动了其他线程,则在其他线程中运行的代码将无法导入任何内容(csr_matrix()
和 ndarray.__repr__()
import其他模块),因为主线程仍然持有导入锁。
关于与打包和mayavi相关的Python死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20600527/