python 导入挂起

在工作中遇到一个导入挂起的问题,花费了很长的时间才解决,

记录一下。

问题简单的复现如下:

a.py:

<span style="font-size:18px;">#coding: utf-8
import datetime
import b</span>
b.py:

#coding: utf-8
import threading
import sys

def test():
    print 'before import datetime'
    import datetime
    print 'after import datetime' 

thd = threading.Thread(target=test)
thd.start()
print 'before b.join'
thd.join()
print 'after b.join'
单独执行python b.py是没有任何问题的,但是如果执行python a.py的话,

程序会停在thd.join()这段代码处。如果把test函数中的import datetime给

去掉的话,则python a.py也没有任何的问题。问题就出在import datetime

上。先看一下官网上怎么说的。

While the import machinery is thread-safe, there are two key restrictions 

on threaded imports due to inherent limitations in the way that thread-safety 

is provided:

   1.Firstly, other than in the main module, an import should not have the 
side effect of spawning a new thread and then waiting for that thread  in  any way. 
Failing to abide  by this restriction can lead to a deadlock if the spawned thread 
directly or indirectly attempts to import a module.
我只摘录了导入挂起相关的部分。从官网解释的来看,主要是因为在import的
时候,使用了import mchinery,而且import mchinery是线程安全的。也就是
说,当有一个线程占用了import mchinery就相当于加锁了,如果其他的线程
想import,那么必须获取这个锁才行。 现在回到我们的例子,在我们执行python 
a.py 的时候执行到了import b,主线程获取了import mchinery的lock,那么继
续向下执行。 在导入b的过程中,创建了另一线程C并且线程C中import了datetime
所以线程C尝试着去获取import  mchinery 的lock, 而此时import  mchinery的
lock被 主线程拥有,并且还没有释放呢, 所以线程 C只能等import mchinery的
lock被释放,而 此时主线程只有等到线程C结束之后,才能释放import mchinery
的lock, 很显然,这里形成 了死锁。所以导入执行到thd.join()时就因为死锁而挂起了。
解决的方法就是不要在新创建的线程中导入任何模块,把需要导入的模块在一开始就
导入进去。
还有一个值得奇怪的问题的是,为啥直接python b.py没有问题呢,这个也是在新创
建的线程 中import的啊,个人认为主要是因为python b.py的时候,创建线程C的时候
没有任何线程在占用着import mchinery的lock,所以直接执行python b.py的时候,
线程C的导入不会形成死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值