Python:模块全局变量的生存期

Python:模块全局变量的生存期,python,global,lifecycle,cpython,Python,Global,Lifecycle,Cpython,我有一个高初始化成本的共享资源,因此我希望在整个系统中访问它(它基本上用于某些仪器,因此必须很轻)。所以我创建了一个模块来管理设置和访问它。它对资源进行惰性初始化,并将其存储在模块全局变量中。然后,我在整个系统中使用此模块的功能对资源进行操作 -现在我想知道是否(或多久一次)必须重新初始化资源 -我知道对象是在CPython(或者更好的情况下)零引用计数的情况下进行垃圾收集的,但是存储在模块中的对象是否被计数为引用,即使此时模块没有被执行 代码示例:这里有一个模块,其中_connect()很慢。

我有一个高初始化成本的共享资源,因此我希望在整个系统中访问它(它基本上用于某些仪器,因此必须很轻)。所以我创建了一个模块来管理设置和访问它。它对资源进行惰性初始化,并将其存储在模块全局变量中。然后,我在整个系统中使用此模块的功能对资源进行操作
-现在我想知道是否(或多久一次)必须重新初始化资源
-我知道对象是在CPython(或者更好的情况下)零引用计数的情况下进行垃圾收集的,但是存储在模块中的对象是否被计数为引用,即使此时模块没有被执行

代码示例:这里有一个模块,其中_connect()很慢。我希望在整个系统中安全地使用report_(),并尽可能少地调用_connect()

__metrics = None


def _connect():
    global __metrics

    client = SomeSlowToSetUpClient()
    __metrics = SomeMetrics(client)
    client.connect()


def report_safely():
       if not __metrics:
           _connect()

       __metrics.execute_lightweight_code()

如果包含全局变量的模块从执行开始到结束都在作用域中,那么全局变量将被删除。但是使用类实例可能会更干净。

不再被引用的对象确实会被垃圾收集(当引用计数下降到0时,它们会被自动删除)

然而,全局模块的引用计数永远不会降到0;导入模块对象(其名称空间)后,将位于
sys.modules
映射中。名称空间本身引用您的对象


换句话说,您的对象将永远存在,直到您从模块名称空间中删除它、删除模块名称空间本身(
del sys.modules['yourmodule']
)或退出python脚本为止。

要问的一个问题是,你确定在第一次连接之后一直连接这个东西是个好主意吗?嗯,这个东西只是向服务器发送UDP数据包,所以我认为保持连接没有问题?听起来不错。谢谢你,玛蒂恩!但是现在我想知道脚本退出意味着什么。上下文是一个Django应用程序,导入这个东西的模块在(芹菜)工作线程中执行。这是否意味着在每个工作线程终止时都会执行该模块,或者父线程的生存期是否计算在内?我是说。。。我可以在生成父线程中的某个地方导入它,但这听起来有点愚蠢。@Zakum:Cellery workers只导入代码一次,然后在线程中运行任务。。。。这意味着我很好,只要芹菜还在继续。太好了,非常感谢!(为了以防万一,我会让这件事再公开几个小时/发表意见,但看起来你对公认的答案有强烈的要求)类似Java的Singleton也是我的第一个想法,但这似乎很不和谐,因为我只有@classmethods和classvariables。另外,垃圾收集也会在单例类中出现同样的问题。