【问题标题】:Python hook for module initialization用于模块初始化的 Python 钩子
【发布时间】:2012-10-11 13:36:03
【问题描述】:

我有一个 python module_A 正在做这样的事情:

myvar = "Hello"

def message():
    print myvar

从另一个模块,我想导入函数message

from module_A import message

但这定义了myvar,这是我不想要的(原因与此处无关)。我想我需要区分 importing 从模块中的东西和 使用 任何导入的符号。我实际上希望myvar 在我使用message 时被初始化

是否有任何类型的 python 钩子可以用来在访问函数或类时初始化东西?我想要类似于以下内容:

module_setup_done = False
def setup():
    global module_setup_done, myvar
    if not module_setup_done:
        myvar = "Hello"
        module_setup_done = True

def message():
    setup()
    print myvar

但是,为了减少混乱,我希望自动调用它,如下所示:

def _init_module():
    global myvar
    myvar = "Hello"

def message():
    print myvar

_init_module() 只会被调用一次,并且只有在模块中的某些东西第一次被访问时,而不是在某些东西被导入时 em>。

python中是否支持这种模式?

【问题讨论】:

    标签: python module initialization


    【解决方案1】:

    不,对此没有内置支持。如果您想与导入模块分开初始化事物,请编写一个执行该初始化的函数,然后在您想要初始化这些事物时调用该函数。如果您想在调用其他事物时“自动”初始化事物,则必须使用您已经发布的代码自己处理。

    但是,如果您发现自己这样做了,那么您可能正在做一些非 Python 的事情。你没有详细说明你为什么在这里这样做,但一般来说,这种隐式初始化在 Python 中不是一个好的做法。当你明确地告诉它们被初始化时,例如通过导入模块或调用某种初始化函数来初始化事物。为什么你觉得需要这个单独的、隐式的初始化步骤?

    【讨论】:

    • 我将尝试总结一下:我的全局变量实际上是 celery 模块中的一个缓存线程,其中定义了一些 celery 任务。我有这个 celery 模块的客户端,它必须导入 celery 任务,但并不真正执行任务(它只会通过 celery 代理它们)。关键是,当我对客户端进行单元测试时,因为它正在从 celery 模块导入符号,所以缓存线程被初始化并启动,即使客户端根本不需要这样做。由于这个 supurious 线程,单元测试没有结束。
    • 在这种情况下,更简单的解决方案可能是根据您是否正在运行测试在 myvar 周围使用 if/else。大概有一些方法可以区分正常执行和单元测试执行,然后你可以这样做:myvar = caching_thread if not in_test_mode else None
    • 是的,我会按照 Jeremy Lewis 的建议去做。你真正想做的是以某种方式标记测试使用并在这种情况下以不同的方式做事。一种方法就是像我描述的那样拥有一个初始化函数,而不是在测试期间调用它。然后您必须手动调用它以进行非测试使用,但这还不错。
    • 您可以使用 __ 来指定不会在调用模块中导入的变量 - 这样它们将被“名称损坏”,因此可以保证它们不会干扰。 stackoverflow.com/questions/1301346/… 有更多相关信息。
    猜你喜欢
    • 2011-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-11-09
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-30
    相关资源
    最近更新 更多