2017-09-19 246 views
0

我有一个简单的程序Base.py,它测试import是否能够在模块不存在时抛出异常。默默杀死线程

# Base.py 
import threading, os, time 
import_is_working = False 

class Launch(threading.Thread): 
    def __init__(self): 
     threading.Thread.__init__(self) 
     self.start() 
    def run(self): 
     global import_is_working 
     try: 
      print "Yes, it got into the 'try' block" 
      import NON_EXISTENT_MODULE 
      assert False 
     except: 
      print "Great, your python language is working" 
      import_is_working = True 
Launch() 
for i in range(500): 
    time.sleep(0.01) 
    if import_is_working: 
     break 
if not import_is_working: 
    print "Your import is not working." 
    os._exit(4) 

有时候,我喜欢另一个模块Main.py使用此代码:

max% python Base.py 
Yes, it got into the 'try' block 
Great, your python language is working 
max% python Main.py 
Yes, it got into the 'try' block 
Your import is not working. 
max% 

这发生在:

# Main.py 
import Base 

出人意料的是,它不会,当我运行它的工作方式Ubuntu,还有一个干净的CentOS 7.3安装。

+0

只是建议:无论何时捕捉异常,都要将异常(也可能是堆栈跟踪)添加到报告方案中。例如...例外情况除外:... – redlus

回答

2

您正在进入“导入锁定”。

documentation提到在线程中导入,您违反了第一个(重点煤矿)的局限性:

虽然进口机器是线程安全的,也有上螺纹进口两个关键 限制由于 方式固有的局限性,提供的是线程安全:

首先,除主模块中的其他,进口不应该产生一个新的线程,然后等着那个 线程的副作用任何方式。如果产生的线程直接或间接尝试导入模块,则不遵守此限制可能导致 死锁。其次,在解释器开始关闭之前,必须完成所有导入尝试。通过线程模块只执行从非守护线程创建 的导入,可以非常容易地实现 。使用线程模块直接创建 的守护程序线程和线程将需要某种其他形式的 同步,以确保它们在系统 关闭开始后不会尝试导入。不遵守此限制将导致 在解释器关闭期间导致间歇性异常和崩溃(因为 延迟导入尝试访问不再处于有效状态的机器)。

+0

谢谢。这回答了我关于为什么我的程序挂起的具体问题。我不知道这个导入锁。当然,这会带来更多的问题,我会在各种情况下提出有关如何最好地避免此问题的新问题。我仍然觉得我们应该清理这个例子来成为一个遵循最佳实践的真实例子(这个问题仅在我使用'setuptools'开始](https://stackoverflow.com/questions/46326059/)时出现,但隔离这种情况需要更长的时间)。但是,如果我们不能编辑这个问题,那么拯救世界就可以等待。 –