【问题标题】:What is import lock in python?python中的导入锁是什么?
【发布时间】:2011-01-21 00:47:06
【问题描述】:

我正在阅读“信号量小书”,其中他有一些代码可以使 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()

【问题讨论】:

  • 你不能用try - except KeyboardInterrupt 包裹你的程序来完成它吗?为什么要为此创建单独的流程?
  • 作为参考,我删除的答案作为评论:对我来说,使用 IPython 时会发生此错误,但使用 vanilla Python 解释器时不会发生此错误。但是 Zach 没有使用 IPython,所以这不是他的原因。
  • @ulidtko 我认为这样您就不必将其放在每个程序的末尾。由于这是书上的,大部分程序都是小程序,所以我想用一个导入解决问题会更容易。
  • @Sven Marnach 我在 mac os x 上使用了 32 位版本的 python 2.7。在默认安装的 python 2.6 中,代码运行良好,所以我猜它只是我的解释器。
  • @Zach:非常奇怪的问题。我认为值得在 Python 开发者邮件列表中询问。

标签: python multithreading


【解决方案1】:

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

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

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

一般来说,Python 模块执行的代码应该只用于初始化全局和单例。

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

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

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

【讨论】:

  • 这就是我最终要做的。 (在导入后调用)但是,当不在 cmd 行解释器上时也会发生这种情况。这很烦人。不过这确实有道理。在 python2.6 中,它不会对我造成问题。 2.7有问题。无论哪种方式,在导入后调用 watcher 似乎都是一种合理的解决方法。
  • @Zach:我猜2.7会在fork后重置导入锁以免造成死锁:bugs.python.org/issue6380
  • 预期行为在multiprocessing 模块的文档中。
【解决方案2】:

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

导入锁是 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

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

【讨论】:

  • 生成进程也是如此,例如“确保新的 Python 解释器可以安全地导入主模块,而不会导致意外的副作用(例如启动新进程)。” - docs.python.org/3/library/…
猜你喜欢
  • 2014-05-05
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 2012-05-07
  • 1970-01-01
  • 2018-07-20
  • 2022-01-07
  • 2010-10-02
相关资源
最近更新 更多