我得出的结论是,我的主模块正在重新加载,并且在此过程中,所有变量都重新初始化为它们的初始状态。
我无法提供一个最小的可复制示例。谷歌搜索之后,除了没有明确告知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
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
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。