如何在Python中检测或防止相同模块的多个实例?
简而言之:在Python中,创建同一模块的多个实例太容易了, 每个实例都有自己的一组全局变量 我需要在模块中添加一个检查来检测这样的多个实例化 并提出一个例外 我的问题与此相同: 这是再现问题的最小目录结构:如何在Python中检测或防止相同模块的多个实例?,python,import,module,instance,Python,Import,Module,Instance,简而言之:在Python中,创建同一模块的多个实例太容易了, 每个实例都有自己的一组全局变量 我需要在模块中添加一个检查来检测这样的多个实例化 并提出一个例外 我的问题与此相同: 这是再现问题的最小目录结构: /test/a/__init__.py /test/a/aa.py: print "aa: __name__: ", __name__ /test/b/b.py: from a import aa import aa 然后 印刷品: aa: __name__: a.aa aa:
/test/a/__init__.py
/test/a/aa.py:
print "aa: __name__: ", __name__
/test/b/b.py:
from a import aa
import aa
然后
印刷品:
aa: __name__: a.aa
aa: __name__: aa
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
...
因此,模块aa.py以不同的名称导入了两次
不用说,模块aa.py将得到两组全局变量,
这破坏了模块内部的所有逻辑
当然,在上面这个简单的例子中,用眼睛很容易发现错误,
但在具有多个子目录的复杂项目中,这些错误会定期出现
所以,我需要一些真正的全局变量或进程范围的存储或类似的东西。
有什么想法吗
编辑:
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)
正在运行
印刷品:
aa: __name__: a.aa
aa: __name__: aa
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有两个实例。如果我尝试在这个模块中实现一个单例,那么这个单例将有两个实例,以此类推
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__
它似乎工作正常(只要我不在多个线程上调用导入)。有人有更好的吗?这是一个难看的解决方法,但您可以使用os.environ[]设置环境变量。 我不太喜欢它,因为它污染了eviroment变量 以下是如何设置这些参数: 祝你好运,
Guy问题在于,您正在使模块从路径中的两个不同条目可用 这是不应该发生的事情,您应该将整个项目目录放在路径中,并且所有模块导入都使用完整路径进行导入,而不管项目内的位置如何,因此,与您的示例不同,它应该是:
export PYTHONPATH=/test
python /test/b/b.py
您将始终需要使用导入,如b.py的第一行:
from a import aa
aa.py将获得2组全局变量
。你能举个例子吗?从我看到的情况来看,Python读取aa.py两次,因此执行print语句两次,b.py仍然只有一个全局变量aa
<代码>\uuuu名称\uuuu在导入时仅显示模块名称。它也可以是\uuuu main\uuuu
,具体取决于您执行它的方式。可以使用def setV(x):全局v,v=x和getV():全局v,返回v。我很确定它不会工作,因为模块是两次导入的谢谢,我将使用os.environ