【问题标题】:How to detect or prevent multiple instances of the same modules in Python?如何在 Python 中检测或防止相同模块的多个实例?
【发布时间】:2026-02-20 00:25:02
【问题描述】:

简而言之:在 Python 中创建同一个模块的多个实例太容易了, 每个实例都有自己的一组全局变量。

我需要在模块中添加一个检查来检测这样的多重实例化 并引发异常。

我的问题和这个一样: Module imported multiple times

这是重现问题的最小目录结构:

/test/a/__init__.py

/test/a/aa.py:
print "aa: __name__: ", __name__

/test/b/b.py:
from a import aa
import aa

然后

export PYTHONPATH=/test:/test/a
python /test/b/b.py

打印:

aa: __name__:  a.aa
aa: __name__:  aa

因此,模块 aa.py 以不同的名称导入了两次。

不用说模块aa.py会得到2组全局变量, 这搞砸了这个模块内的所有逻辑。

当然,在上面的简单示例中,很容易通过眼睛检测到错误, 但是在具有多个子目录的复杂项目中,这些错误会定期弹出。

所以,我需要一些真正的全局变量或进程范围的存储或类似的东西。 有什么想法吗?

编辑: Bibhas 要求提供同一全局变量的多个实例的示例。这里是:

/test/a/__init__.py

/test/a/aa.py:
print "aa: __name__: ", __name__

import thread
import time

test_var = __name__

def test():
    for i in range(0,5):
        print "aa thread: test_var: ", test_var
        time.sleep(1)

thread.start_new_thread( test, () )

/test/b/b.py:

print "b: __name__: ", __name__

from a import aa
import aa

import time
time.sleep(10)

正在运行

export PYTHONPATH=/test:/test/a
python /test/b/b.py

打印:

aa: __name__:  a.aa
aa: __name__:  aa
aa thread: test_var:  aa
aa thread: test_var:  a.aa
aa thread: test_var:  aa
aa thread: test_var:  a.aa
...

因此,很明显变量 test_var 有 2 个实例。如果我尝试在这个模块中实现一个单例,就会有这个单例的 2 个实例,等等。

Edit2:所以,Guy L 建议的解决方案类似于:

/test/a/aa.py:
import os
if "aa.py" in os.environ:
    raise Exception("Duplicate instantiation of aa.py")
os.environ["aa.py"] = __name__

它似乎工作正常(只要我不在多个线程上调用 import)。谁有更好的?

【问题讨论】:

  • aa.py will get 2 sets of global variables。你能举个例子吗?从我看到的 Python 读取 aa.py 两次,因此执行 print 语句两次,b.py 仍然只有一个全局变量 aa__name__ 只是在导入时显示模块名称。它也可能是__main__,这取决于你如何执行它。
  • 也许可以使用 def setV(x): global v, v =x and getV(): global v, return v。我很确定它不会工作,因为模块被导入了两次

标签: python import module instance


【解决方案1】:

这是一个丑陋的解决方法,但您可以使用 os.environ[] 来设置环境变量。 我不太喜欢它,因为它会污染环境变量。

您可以通过以下方式进行设置: http://code.activestate.com/recipes/159462-how-to-set-environment-variables/

祝你好运, 伙计

【讨论】:

  • 谢谢,我会用os.environ
【解决方案2】:

问题是您正在使模块可从路径中的两个不同条目中使用。

这是不应该发生的事情,您应该将整个项目目录放在路径中,并且无论项目内的位置如何,所有模块导入都使用完整路径进行导入,因此,应该是:

export PYTHONPATH=/test
python /test/b/b.py

而且你总是需要像 b.py 的第一行那样使用导入:

from a import aa

【讨论】:

    最近更新 更多