什么是python中的导入锁?

时间:2011-01-21 00:47:06

标签: python multithreading

我正在阅读“信号量小书”,其中有一些代码可以让python使用与他在本书中使用的语法类似的语法。但是,当我尝试导入他的代码时,它会给我以下错误。

from threading_cleanup import *
RuntimeError: not holding the import lock

我知道它与观察者功能代码有关,因为如果我将其注释掉,那么错误就会消失,那里的代码就可以了,所以我可以使用KeyboardInterrupt结束程序。

有没有办法解决错误?

threading_cleanup.py

import threading
import time
import os
import signal
import sys

__all__ = ['Thread', 'Semaphore', 'watcher']

class Thread(threading.Thread):
    def __init__(self, target, *args):
        threading.Thread.__init__(self, target=target, args=args)
        self.start()


class Semaphore(threading._Semaphore):
    wait = threading._Semaphore.acquire

    def signal(self, n=1):
        for _ in range(n): self.release()

    def value(self):
        return self._Semaphore__value


def watcher():
    child = os.fork()
    if child == 0: return
    try:
        os.wait()
    except KeyboardInterrupt:
        print 'KeyboardInterrupt'
        os.kill(child, signal.SIGKILL)
    sys.exit()


watcher()

2 个答案:

答案 0 :(得分:1)

在我的设置中,错误仅在解释模式下发生。

似乎解释器不喜欢模块在仍然导入时执行分叉。

如果您移除watcher()电话或将其包裹在if __name__ == '__main__':中,则错误消失。

通常,Python模块执行的代码应仅用于初始化全局变量和单例。

哦!导入后,您可以从解释器中调用threading_cleanup.watcher(),并且不会引发异常。

哎!我意识到我没有回答你问题的标题:

fork()的调用会创建一个新的解释程序;一个必须导入模块才能开始执行的模块。在解释模式下,您在模块仍在导入时会发生这种情况,从而被锁定。在解释模式中,交互式解释器是主程序。在执行模式下,如在python mymodule.py中,模块是主程序,因此它不会导入。这有意义吗?

答案 1 :(得分:0)

这个问题的标题询问进口锁是什么。

导入锁是Python的import实现的一部分,如果你违反了这些模糊的限制,会导致程序失败:

https://docs.python.org/2/library/threading.html#importing-in-threaded-code

在您的情况下,因为您直接在模块中调用watcher(),所以除非该模块恰好是主模块,否则它无法启动线程。这是一个例子:

python2.7 - import silently locks up the thread

您的示例似乎有点不同,因为它涉及进程。如果我将threading_cleanup.py缩减为:

import os
def watcher():
    child = os.fork()
watcher()

我仍然得到同样的错误:

  File "main.py", line 1, in <module>
    import threading_cleanup.py
RuntimeError: not holding the import lock

所以,这不是一个进口锁。除了错误消息说它是一个导入锁,现在不是吗?听起来像错误消息文本中的错误。