【发布时间】:2013-12-15 22:13:58
【问题描述】:
我有一个奇怪的问题,希望有人能解释一下。
我有一段复杂的代码,从一个充满脚本的目录开始,我决定将其重新编写成一个包。此代码更改似乎是一些奇怪死锁出现的触发因素。
下面是对该问题进行规范再现的尝试;失败了,因为此代码按预期运行。实际重现问题可能需要大量代码;但我无法想象在上下文中违规代码 sn-p 有什么不同。
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 线程,但它们又不知何故无法再次获得焦点?
非常感谢任何有助于进一步缩小这个谜团的提示!
【问题讨论】:
-
很难说,因为问题可能与您没有在此处复制的代码细节有关。你
join()ing 这些线程中的任何一个吗?您是否像您给我们的示例一样在模块的顶层启动它们?如果您正在做这两件事,那么这就是文档中的评论告诉您不要做的事情。在执行模块代码时,会持有一个全局导入锁。以这种方式调用csr_matrix()确实会导致导入,因此它也会尝试获取导入锁。出现僵局。不要那样做。 -
感谢您的帮助。这就是我对文档的理解;但我没有做这两件事。我不会在任何地方加入任何事情。也许 mayavi 在幕后做某事;但这不是文档警告的内容,不是吗?线程从 UI 对象中的方法启动,作为对用户输入的响应。此外,此时 csr_matrix 早已被导入其他地方;它应该被缓存,所以导入锁仍然起作用吗?
-
还有;关于是什么让 csr_matrix 和 ndarray.__repr__ 特别的任何线索?为什么我的线程在到处乱跑的代码中愉快地前进; numpy scipy 和一大堆导入,但无论我在哪里调用这两个函数中的任何一个,都会一直卡住?
-
在密集的
ndarraycauses an import 上调用csr_matrix()。如果你能想出一个完整的例子来说明这个问题,我也许可以提供帮助。 -
当您说您使用 Mayavi 时,您的意思是您在脚本中使用
mlab.show(),而不是将您的代码集成到 Mayavi 应用程序中?
标签: python multithreading packaging mayavi