与打包和mayavi相关的Python死锁?

与打包和mayavi相关的Python死锁?,python,multithreading,packaging,mayavi,Python,Multithreading,Packaging,Mayavi,我有一个奇怪的问题,希望有人能解释一下 我有一段复杂的代码,从一个充满脚本的目录开始,我决定将其重新编写成一个包。这种代码更改似乎触发了一些奇怪的死锁出现 下面是对这个问题的规范再现的尝试;这失败了,因为这段代码按预期运行。实际复制问题可能需要大量代码;但是,在我的一生中,我无法想象上下文中令人不快的代码片段会有什么不同 import numpy as np from scipy.sparse import csr_matrix from threading import Thread def

我有一个奇怪的问题,希望有人能解释一下

我有一段复杂的代码,从一个充满脚本的目录开始,我决定将其重新编写成一个包。这种代码更改似乎触发了一些奇怪的死锁出现

下面是对这个问题的规范再现的尝试;这失败了,因为这段代码按预期运行。实际复制问题可能需要大量代码;但是,在我的一生中,我无法想象上下文中令人不快的代码片段会有什么不同

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()
也许文档中的这个简短评论是相关的?我不确定我是否完全理解这里所说的话

首先,除了在主模块中,导入不应该产生产生新线程然后以任何方式等待该线程的副作用。如果生成的线程直接或间接尝试导入模块,如果不遵守此限制,可能会导致死锁

一些上下文:我正在使用Python2.7,Numpy1.8,在那里我尝试从mayavi/traitsui线程中生成这个新线程(我不明白为什么它应该相关,在包结构之前它工作得很好,但还可以)。此外,在我生成的线程中有大量numpy/scipy代码,执行得非常好;它只是打印NDARRAY并创建稀疏矩阵,到目前为止,这些矩阵已被证明是死锁的触发器

我怀疑与mayavi之间有什么奇怪的交互,因为关闭mayavi窗口会导致所有死锁的线程重新开始运行。也许这些特定的语句触发python线程返回到mayavi线程,但它们不知何故无法再次获得关注


任何能进一步缩小这个谜团的线索都将不胜感激

从您的评论来看,您似乎在一个子模块的顶层启动了UI事件循环。这不是一个好主意,因为它会导致与文档中提到的问题完全相同的问题<代码>导入foo不应启动UI事件循环。问题是主线程抓住导入锁来处理模块的导入。此模块在完成导入之前启动UI事件循环。这与等待其他线程完成的情况基本相同;您正在等待UI循环完成。如果您的UI启动了其他线程,则在其他线程中运行的代码将无法导入任何内容(包括
csr\u matrix()
ndarray.\uuu repr\uuuu()
导入其他模块),因为主线程仍保持导入锁。

很难说,因为问题可能与您没有在此处复制的代码的细节有关。您是否正在
join()
ing这些线程中的任何一个?您是否在模块的顶层启动它们,如您给我们的示例所示?如果您同时做这两件事,那么文档中的注释就是告诉您不要这样做。在执行模块的代码时,存在一个全局导入锁。以这种方式调用csr\u matrix()确实会导致导入,因此它还会尝试获取导入锁。僵局接踵而至。不要那样做,谢谢你的帮助。我就是这样理解这些文件的;但这两件事我都不做。我不会加入任何组织。也许马亚维在幕后做了些什么;但这不是医生警告的,不是吗?线程从UI对象中的方法启动,作为对用户输入的响应。此外,csr_矩阵早已被引入其他地方;它应该被缓存,那么导入锁是否仍然起作用;关于csr矩阵和ndarray的特殊性有什么线索吗?为什么我的线程在代码中快乐地行进;numpy scipy和大量导入,但无论我在哪里调用这两个函数,都会一直被卡住?在密集的
ndarray上调用
csr\u matrix()
。如果你能拿出一个完整的例子来说明这个问题,我也许能帮上忙。当你说你在使用Mayavi时,你的意思是你在脚本中使用
mlab.show()
,而不是将你的代码集成到Mayavi应用程序中吗?我明白了;configure_traits创建一个线程,然后等待它,这违反了文档中指定的规则(如果mayavi文档强调这一点,这不会有什么坏处)。然而,我不明白的是,死锁只有在使用非常狭窄的函数子集时才会发生(同样,在mayavi线程和它的子线程中,大量的代码与导入混杂在一起,执行起来没有问题)。我仍然不能说我完全理解这里发生的事情,我必须说,我对这一切的pythonicity有点失望。但尽管如此,仔细阅读文档并坚持到底确实解决了问题。感谢你的来来回回;即使我最终找到了答案,我也会接受这个答案。
configure\u traits()
不会创建线程。它只运行UI循环,直到UI循环完成才返回。所有UI循环的行为都是这样的。告诉你这些。我希望您正在使用的线程中没有一个真正导入线程内部的东西,比如调用
csr\u matrix()
ndarray.\uu repr\uu()
只使用线程启动前导入到模块命名空间中的模块。我的印象是所有traits应用程序都在内部使用多个线程?但无论如何;对configure_traits()的调用被阻塞,因此我的工作线程仍然是导入的间接副作用,因此导入锁仍然存在。但是如果configure_traits()没有创建线程,这是否会导致文档不完整?问题应该是在模块级创建一个线程,然后连接它。但再一次;我不等待任何线程。如果mayavi/traits有