关于多线程:python中的导入锁是什么?

What is import lock in python?

我在读《信号量小书》,他在书中有一些代码可以让Python使用与书中类似的语法。但是,当我尝试导入他的代码时,会出现以下错误。

1
2
from threading_cleanup import *
RuntimeError: not holding the import lock

我知道它与观察者功能代码有关,因为如果我把它注释掉,错误就消失了,那里的代码就消失了,所以我可以使用键盘中断来结束程序。

有什么方法可以修正这个错误吗?

线程清理.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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()


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

似乎解释器不喜欢模块在导入时执行fork。

如果删除watcher()调用或将其包装在if __name__ == '__main__':中,错误就会消失。

通常,由Python模块执行的代码应该只用于全局和单例初始化。

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

嗯!我意识到我没有回答你问题的题目:

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


这个问题的标题询问导入锁是什么。

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

https://docs.python.org/2/library/threading.html导入线程代码

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

python2.7-导入会自动锁定线程

不过,您的示例似乎有点不同,因为它涉及流程。如果我把你的threading_cleanup.py减少到:

1
2
3
4
import os
def watcher():
    child = os.fork()
watcher()

我仍然会得到同样的错误:

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

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