kbengine进阶的热更新方案

imp.reload可以重载模块,但是关键问题是已经实例化过的类是不会变的
比如:

  1. class AA:
  2.     def testaa():
  3.         DEBUG_MSG("test")
  4.                
  5. self.a=AA()

复制代码

使用imp.reload热更新后a还是不会变,需要重新把self.a.__class__=AA才能完成热更新
这样非常得不方便
一种可行的做法就是实例化类的时候把类都存到一个地方,然后热更新的时候全部把它们的__class__修改一下就行了

一开始用的装饰器的方式,但是有一些局限性,还是用继承的方式

  1.  
  2. g_allReloadObjectList=[]
  3. class Reload:
  4.     __reload__=True
  5.     def __init__(self):
  6.         g_allReloadObjectList.append(weakref.ref(self))

复制代码

创建类的时候就像:

  1. class AA(Reload):
  2.     def __init__(self):
  3.         Reload.__init__(self)

复制代码

就可以在实例化类的时候把实例存到g_allReloadObjectList里面

下面的代码写得比较垃圾,但是简单易懂:
reloadAllModule的功能是遍历base cell common user_type几个文件夹的所有文件,然后全部重载,感觉有点暴力,可以优化成只加载修改过的文件
同时把文件里需要热更新的类存到g_allClasses里
然后把g_allReloadObjectList里存的那些的实例的__class__全部改成g_allClasses里的
reloadSystem.py

  1. import inspect
  2. import os
  3. import importlib
  4. import imp
  5. import copy
  6. import weakref
  7. import KBEngine
  8. from KBEDebug import *
  9. if 0:
  10.     from baseapp import KBEngine
  11. if 0:
  12.     from cellapp import KBEngine
  13.  
  14. #需要把此文件加入热更新黑名单
  15. _blackList=["reloadSystem"]
  16. g_allClasses={}
  17.  
  18. g_allReloadObjectList=[]
  19. class Reload:
  20.     __reload__=True
  21.     def __init__(self):
  22.         g_allReloadObjectList.append(weakref.ref(self))
  23.  
  24. def reloadAllModule():
  25.     global g_allClasses
  26.     g_allClasses={}
  27.     #base cell common user_type文件夹内的所有py全部重载
  28.     if KBEngine.component=="baseapp":
  29.         sb=KBEngine.getResFullPath("base/kbemain.py")
  30.         sb=sb[:-10]
  31.         ll=len(sb)
  32.         for s in KBEngine.listPathRes("base","py"):
  33.             s=s[ll:-3]
  34.             s=s.replace('/','.')
  35.             mo=importlib.import_module(s)
  36.             _reloadModule(mo)
  37.     elif KBEngine.component=="cellapp":
  38.         sb=KBEngine.getResFullPath("cell/kbemain.py")
  39.         sb=sb[:-10]
  40.         ll=len(sb)
  41.         for s in KBEngine.listPathRes("cell","py"):
  42.             s=s[ll:-3]
  43.             s=s.replace('/','.')
  44.             mo=importlib.import_module(s)
  45.             _reloadModule(mo)
  46.     #reload common
  47.     sb=KBEngine.getResFullPath("common/cfunc.py")
  48.     sb=sb[:-8]
  49.     ll=len(sb)
  50.     for s in KBEngine.listPathRes("common","py"):
  51.         s=s[ll:-3]
  52.         s=s.replace('/','.')
  53.         mo=importlib.import_module(s)
  54.         _reloadModule(mo)
  55.     #reload userType
  56.     sb=KBEngine.getResFullPath("user_type/UserType.py")
  57.     sb=sb[:-11]
  58.     ll=len(sb)
  59.     for s in KBEngine.listPathRes("user_type","py"):
  60.         s=s[ll:-3]
  61.         s=s.replace('/','.')
  62.         mo=importlib.import_module(s)
  63.         _reloadModule(mo)
  64.  
  65.     _reloadAllObjects()
  66.  
  67.  
  68. """
  69. 重载模块,然后把模块里面的需要重载的类全部加
  70. """
  71. def _reloadModule(mo):
  72.     if mo.__name__ in _blackList:
  73.         return
  74.     imp.reload(mo)
  75.     for name,Cls in inspect.getmembers(mo):
  76.         if getattr(Cls,'__reload__',False):
  77.             path=inspect.getsourcefile(Cls)
  78.             g_allClasses[path+Cls.__name__]=Cls
  79.  
  80.  
  81. def _reloadAllObjects():
  82.     delList=[]
  83.     for ref in g_allReloadObjectList:
  84.         obj=ref()
  85.         if obj:
  86.             n=inspect.getsourcefile(obj.__class__)+obj.__class__.__name__
  87.             if n in g_allClasses:
  88.                 obj.__class__=g_allClasses[n]
  89.             else:
  90.                 WARNING_MSG("not find Class "+n)
  91.         else:
  92.             delList.append(ref)
  93.     for ref in delList:
  94.         g_allReloadObjectList.remove(ref)

复制代码

这样就实现了即时切换__class__

并且可以用Tornado做一个类来接受socket命令然后调用globalData通知全部进程热更新
然后在ide里的externalTools里做个发送socket的小工具,并且设置快捷键
然后只要写了点代码后按一下快捷键,服务端所有进程瞬间更新到最新的代码,生活质量提升了不止一个档次

如果谁有更好的热更新方案欢迎补充

发布了13 篇原创文章 · 获赞 0 · 访问量 2300

猜你喜欢

转载自blog.csdn.net/kbengine/article/details/104882577