Python 跨模块共享一个单例
给出两个模块,main和x,包括以下内容: 主要内容: 和x,分别为:Python 跨模块共享一个单例,python,python-3.x,singleton,Python,Python 3.x,Singleton,给出两个模块,main和x,包括以下内容: 主要内容: 和x,分别为: import main print(id(main.uvw)) print(main.uvw.x) 我现在希望在两个实例中执行main将产生相同的id和值20,但我得到的是: $ python main.py 140592861777168 20 140592861207504 10 有什么方法可以确保uvw在两个位置都是相同的对象吗?我认为问题在于您的单例类不知何故被重新加载,从而在第二个模块中丢失了它的\u实例字段
import main
print(id(main.uvw))
print(main.uvw.x)
我现在希望在两个实例中执行main将产生相同的id和值20,但我得到的是:
$ python main.py
140592861777168
20
140592861207504
10
有什么方法可以确保
uvw
在两个位置都是相同的对象吗?我认为问题在于您的单例
类不知何故被重新加载,从而在第二个模块中丢失了它的\u实例
字段
我认为这会奏效:
singleton.py
:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
cls._instance.x = 10
return cls._instance
from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)
from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)
a.py
:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
cls._instance.x = 10
return cls._instance
from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)
from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)
b.py
:
class Singleton(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
cls._instance.x = 10
return cls._instance
from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)
from singleton import Singleton
uvw = Singleton()
print(id(uvw))
uvw.x += 10
print(uvw.x)
main.py
import a
import b
我发现问题在于当从命令行执行时,
main
被加载了两次,一次作为\uuu main\uuu
加载,第二次作为main
导入
我找到了一个非常邪恶的黑客来绕过第二个负载:
sys.modules["main"] = sys.modules["__main__"]
在我的例子中,分离主模块和单例类是不可取的。Python按名称加载每个模块一次(除非调用了
reload(module)
)。如果运行main.py
,则模块为\uuuuuu main\uuuuu
(请尝试打印uvw.\uuuuuuuu class.\uuuuuuuuuuu模块
)。当x
导入main
时,将首次加载名为main
的模块
如果您在第三个模块中定义了
uvw
,或者在x
中定义了uvw
——只要它以同样的方式导入到\uuuuuuuu main
和x
,它将是同一个对象。我真的不想进一步拆分我的程序。。。这对我来说是最后的手段:)如果你的代码必须从另一个文件导入主模块,那么就会发生可疑的事情sys.modules[''''u____']
不同于sys.modules['x']
@csde_,如果可能的话,将该singleto放入x
模块中。请注意,\u新的
方法的整个要点是防止您需要访问main.uvw
,因为Singleton()
保证每次都返回相同的实例。因此main
正在调用x
哪个正在调用main
。。。?这会造成混乱/灾难。您可能会重复使用\uuuu main\uuuu
和x
模块,这两个模块是单独的名称空间。请参阅副本。为了避免邪恶的黑客攻击,您可以在未作为脚本执行的模块中定义uvw
,然后将该模块导入主脚本