用于模块初始化的Python钩子

用于模块初始化的Python钩子,python,module,initialization,Python,Module,Initialization,我有一个python模块_a,它正在做类似的事情: myvar = "Hello" def message(): print myvar def _init_module(): global myvar myvar = "Hello" def message(): print myvar 我想从另一个模块导入函数消息: from module_A import message 但这是定义myvar的过程,我不想这样做(因为这里没有真正相关的原因)。我想我

我有一个python
模块_a
,它正在做类似的事情:

myvar = "Hello"

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

def message():
    print myvar
我想从另一个模块导入函数
消息

from module_A import message
但这是定义myvar的过程,我不想这样做(因为这里没有真正相关的原因)。我想我需要区分从模块导入东西和使用任何导入的符号。实际上,我只想在使用
消息时初始化
myvar

我是否有任何一种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
但是,为了减少混乱,我希望自动调用此函数,如下所示:

myvar = "Hello"

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

def message():
    print myvar
其中,
\u init_module()
将只调用一次,并且仅在第一次访问模块中的某些内容时调用,而不是在导入某些内容时调用


python中是否支持这种模式?

否,没有对此的内置支持。如果您想在导入模块的同时单独进行初始化,请编写一个进行初始化的函数,然后在需要初始化这些内容时调用该函数。如果您想在调用其他东西时“自动”初始化这些东西,那么您必须按照已经发布的代码来处理这些东西


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

不,没有内置的支持。如果您想在导入模块的同时单独进行初始化,请编写一个进行初始化的函数,然后在需要初始化这些内容时调用该函数。如果您想在调用其他东西时“自动”初始化这些东西,那么您必须按照已经发布的代码来处理这些东西


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

我将尝试总结一下:我的全局变量实际上是芹菜模块中的一个缓存线程,其中定义了一些芹菜任务。我有一个用于芹菜模块的客户端,它必须导入芹菜任务,但并不真正执行任务(它将通过芹菜代理它们)。关键是,当我对我的客户机进行单元测试时,因为它正在从芹菜模块导入符号,所以缓存线程被初始化并启动,即使在客户机中根本不需要这样做。由于这个超级线程,unittest并没有结束。在这种情况下,一个更简单的解决方案可能是根据您是否正在运行测试在myvar周围使用if/else。大概有某种方法可以区分正常执行和单元测试执行,然后你可以这样做:myvar=caching_thread,如果不是在_test_模式下,我会像Jeremy Lewis建议的那样做。您真正想要做的是以某种方式标记测试使用情况,并在这种情况下以不同的方式进行操作。一种方法是使用我描述的初始化函数,而不是在测试期间调用它。然后,您必须为非测试用途手动调用它,但这并不是那么糟糕。您可以使用_uu指定不在调用模块中导入的变量-这样它们将被“名称损坏”,因此保证不会干扰。我将尝试总结:我的全局变量实际上是芹菜模块中的一个缓存线程,其中定义了一些芹菜任务。我有一个用于芹菜模块的客户端,它必须导入芹菜任务,但并不真正执行任务(它将通过芹菜代理它们)。关键是,当我对我的客户机进行单元测试时,因为它正在从芹菜模块导入符号,所以缓存线程被初始化并启动,即使在客户机中根本不需要这样做。由于这个超级线程,unittest并没有结束。在这种情况下,一个更简单的解决方案可能是根据您是否正在运行测试在myvar周围使用if/else。大概有某种方法可以区分正常执行和单元测试执行,然后你可以这样做:myvar=caching_thread,如果不是在_test_模式下,我会像Jeremy Lewis建议的那样做。您真正想要做的是以某种方式标记测试使用情况,并在这种情况下以不同的方式进行操作。一种方法是使用我描述的初始化函数,而不是在测试期间调用它。然后,您必须为非测试用途手动调用它,但这并不是那么糟糕。您可以使用_uu指定不在调用模块中导入的变量-这样它们将被“名称损坏”,因此保证不会干扰。有更多关于这方面的信息。