开发者社区> 问答> 正文

模块在没有明确指示的情况下重新加载和重置

  • TLDR:我想大体上知道,是什么导致模块重新加载并重置为原始状态,而无需我明确尝试将其恢复。*

我得出的结论是,我的主模块正在重新加载,并且在此过程中,所有变量都重新初始化为它们的初始状态。

我无法提供一个最小的可复制示例。谷歌搜索之后,除了没有明确告知python3.x不应重新加载模块外,我在该主题上找不到其他任何内容。

使用pygame 1.9.6。

我想问一下通常是什么导致这种现象。我的主模块示例以及添加的调试打印信息:

import pygame
from sys import exit

class Engine:
    def __init__(self):
        self.init = False
        self.running = False

    def start(self):
        print("engine start called")
        print("self.init state:", self.init)        

        from graphics import render
        render.init()

        from initializer import initializer
        initializer.init_sprites()

        if not self.init:
            self.init = True
            self.running = True

        print("new self.init state:", self.init)

        self.main_loop()

    def update_input(self):
        pass

    def update_events(self):
        pass

    def update_graphics(self):
        pass

    def self.main_loop() # it's at the very end of the real Engine() aswell
        while True:
            self.update_input()
            self.update_events()
            self.update_graphics()

        pygame.quit()
        exit()


engine = Engine()

print("above engine start reached")

app_init = False # I added this purely for debugging reasons

if not app_init:
    app_init = True
    engine.start()

该应用程序不会崩溃或引发异常,因为所有其他模块都可以正常运行。例如,子画面会保留其状态,并保持应有的运动。相机仍可滚动等。

但是,控制台提供:

above engine.start() reached
engine start called
self.init state: False
render.init called
new self.init state: True
#stuff happening in background in other modules, no methods changing self.running or explicitly reloading main module. However imports of engine object do happen
above engine.start() reached
engine start called
self.init state: False
render.init called
new self.init state: True

但:

1)main_loop()永远不会返回

2)打印结果表明,即使While循环应该处于活动状态,主模块的末尾还是以某种方式到达了,如果应用程序经过了main_loop()中的while循环,则应用程序应该退出()

3)将self.init和全局app_init状态重置为硬编码值,并且像第一次初始化模块一样调用engine.start()

这是进口问题吗?

更新:

Not solved. But I have removed all side-effects by preventing all other modules from being re-initialized. However, this seems like a dirty hack and I am afraid that the reloading of my main module will lead to consequences sooner or later.

问题来源: stackoverflow

展开
收起
is大龙 2020-03-24 09:35:04 1017 0
1 条回答
写回答
取消 提交回答
  • It's mostly a wild guess, but the only explanation I can imagine with the infos provided is that some of your "other modules" imports your file. If that's the case, you should restructure your code to avoid circular dependencies. A simple way to check this is to add a guard preventing everything under your class definition to be executed on import:

    class Engine:
        # ...
    
    
    if __name__ == "__main__":
    
        engine = Engine()
    
        print("above engine start reached")
    
        app_init = False # I added this purely for debugging reasons
    
        if not app_init:
            app_init = True
            engine.start()
    

    Also, please move your imports (the ones in Engine.init ) at the module's top-level.

    EDIT :

    An import was the problem (I retrieved deltatime from the engine in another module).

    然后设计问题。

    删除该导入后,引擎将不再重新初始化。我现在使用if name ==“ main”。(...)我不知道在导入模块时,底部的engine = Engine()会重新初始化引擎。

    Python是一种运行时语言-除字节码编译外,其他所有操作均在运行时进行。当第一次加载Python模块(在给定的过程中)时,模块顶层的所有代码都将被执行-这就是函数和类的创建方式(def和class是可执行语句)等-然后将其缓存在sys.modules字典中(在模块名称下)以进行其他导入(因此仅加载一次)。

    现在,将模块用作脚本时,会发生相同的事情,不同的是,该模块是以“ main ” 的名称导入(并缓存)的。因此,当您的其他模块尝试导入主脚本时,加载程序将查找脚本名称,但找不到它(因为它被缓存为“ * main *”,而不是“ youscriptname”),然后重新加载它。这解释了双重加载,但也意味着这两个模块是不同的实例,类是不同的类,而“引擎”实例是不同的实例。

    IOW,而如果名称 ==“ 主 ”后卫阻止脚本的“主”的代码被执行两次,你只掩盖症状,不固定的根本问题。简而言之,您的任何模块都不应尝试访问主脚本中定义的任何内容。

    如果要在其他地方重用在主脚本中定义的函数或类,则应将它们提取到另一个模块。但是,如果另一个模块中的某些内容需要从主脚本访问engine 实例,那么您将不得不重新考虑您的设计以显式地传递engine实例(或需要它的任何内容)。

    回答来源:stackoverflow

    2020-03-24 09:35:13
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载