介绍:

热更新,就是在维持服务不间断的情况下,对软件代码逻辑或配置数据进行更新修复。随着游戏项目引入了脚本语言以后,热更新技术逐渐成为了标配,在我经历过的游戏项目中,无论是服务端还是客户端,版本的更新迭代都是围绕着静态patch和动态patch(热更新)来进行的。下面来谈一下客户端Python热更新的处理。

原理:

标准import

我们知道,import可以导入一个标准的python模块,将模块载入内存,并加到sys.modules中。多次import同一模块只是将名称导入到当前的Local名字空间,也就是一个模块不会重复载入。

reload函数

reload()函数可以重新载入已经导入的模块,这样看起来就可以热更新python模块了。可惜的是,python原生的reload函数远不能满足游戏热更新的问题,原因如下:

reload重新加载的模块不会删除旧版本的模块,也就是已经引用的旧模块无法更新

同样因为不能旧对象的引用,使用from ... import ... 方式引用的模块同样不能更新

reloas(m)后,class及其派生class的实例对象,仍然使用旧的class定义。

加载模块失败时候,没有rollback机制,需要重新import该模块

因此,有必要结合游戏的情景,自定义适合的reload。新的自定义reload目的是为了达到在原程序不结束的情况下,让程序能动态加载改动后的代码。主要想达到下面两点:

提升开发期的开发效率

在游戏不重启的情况下修复紧急BUG

实现:

热更新当中实际的重点在于如何让已经创建的对象获得新代码的变化,以及在reload前后不产生类型上的不一致。刷新function,class内定义的method比较容易实现,但对于刷新module内定义的变量,class内定义的变量,还有新增加的成员变量,则需要有统一的约定。所以,在热更新过程中,我们只要考虑好代码更新和数据更新这两点,那么更新就是可行的。

下面罗列一下新的reload具备哪些特性:

更新代码定义(function/method/static_method/class_method)

不更新数据(除了代码定义外的类型都当作是数据)

在module中约定reload_module接口,class中约定reload_class接口,在这两个接口中手动处理数据的更新,还有更多的约定和接口待完成

替换函数对象的内容

# 用新的函数对象内容更新旧的函数对象中的内容,保持函数对象本身地址不变

def update_function(oldobj, newobj, depth=0):

setattr(oldobj, "func_code", newobj.func_code)

setattr(oldobj, "func_defaults", newobj.func_defaults)

setattr(oldobj, "func_doc", newobj.func_doc)

替换类的内容

# 用新类内容更新旧类内容,保持旧类本身地址不变

def _update_new_style_class(oldobj, newobj, depth):

handlers = get_valid_handlers()

for k, v in newobj.__dict__.iteritems():

# 如果新的key不在旧的class中,添加之

if k not in oldobj.__dict__:

setattr(oldobj, k, v)

_log("[A] %s : %s"%(k, _S(v)), depth)

continue

oldv = oldobj.__dict__[k]

# 如果key对象类型在新旧class间不同,那留用旧class的对象

if type(oldv) != type(v):

_log("[RD] %s : %s"%(k, _S(oldv)), depth)

continue

# 更新当前支持更新的对象

v_type = type(v)

handler = handlers.get(v_type)

if handler:

_log("[U] %s : %s"%(k, _S(v)), depth)

handler(oldv, v, depth + 1)

# 由于是直接改oldv的内容,所以不用再setattr了。

else:

_log("[RC] %s : %s : %s"%(k, type(oldv), _S(oldv)), depth)

# 调用约定的reload_class接口,处理类变量的替换逻辑

object_list = gc.get_referrers(oldobj)

for obj in object_list:

# 只有类型相同的才是类的实例对象

if obj.__class__.__name__ != oldobj.__name__:

continue

if hasattr(obj, "x_reload_class"):

obj.x_reload_class()

staticmethod

def _update_staticmethod(oldobj, newobj, depth):

# 一个staticmethod对象,它的 sm.__get__(object)便是那个function对象

oldfunc = oldobj.__get__(object)

newfunc = newobj.__get__(object)

update_function(oldfunc, newfunc, depth)

classmethod

def _update_classmethod(oldobj, newobj, depth):

oldfunc = oldobj.__get__(object).im_func

newfunc = newobj.__get__(object).im_func

update_function(oldfunc, newfunc, depth)

模块的更新也是相类似,就不一一粘贴了,只是在原来的reload基础上进行改良,对于模块热更新,还约定了一个reload_module接口,可以自定义数据的更新。

下面添加一些用例:

def x_reload_class(self):

""" 热更新后,每个重新对象的实例都会执行这个函数

由于新老对象的替换不会重新调用构造函数,因此有必要对热更新的类对象执行初始化逻辑

处理新老变量的修复,函数执行环境的修复

"""

self._new_var = 5000 # 新变量的初始化

self.init_widget() # 新修复的逻辑

目前的热更新模块已经在开发调试中使用,可以方便地完成一些更新任务,但是要更新到远程客户端,还需要更多的规范和接口来处理,如闭包,内部局部变量等,需要逐步地学习和完善。

python flask热更新_客户端python热更新相关推荐

  1. python生成word目录_使用Python更新MS Word .docx文档的目录(目录)

    我使用python包" python-docx"来修改MS Word .docx文档的结构和内容.该软件包无法更新TOC(目录)[Python: Create a "Ta ...

  2. war包热更新_基于IDEA热部署更新服务器Tomcat类,服务器Tomcat热更新

    前言 在开发过程中,如果我们是使用的IDEA,就会知道IDEA有一个热更新的功能,何为热更新?就是在不重启Tomcat的情况下让服务器中的代码变更为最新的.这样既能快速的更新代码,又不用担心Tomca ...

  3. python生成json接口_基于python的Flask框架写json接口并且结合eolinker进行接口测试

    一.前言 很多时候为了提高软件开发的效率,后端程序人员理想状态下应该编写程序测试接口供前端程序人员进行测试,以便前端的开发.笔者由于项目的需求近期尝试学习了一下测试接口的编写,以Python+Flas ...

  4. python 服务端渲染_客户端渲染与服务端渲染

    后端渲染 服务器直接生成HTML文档并返回给浏览器,但页面交互能力有限.适用于任何后端语言:PHP.Java.Python.GO等. 客户端渲染(CSR) 页面初始加载的HTML文档中无内容,需要下载 ...

  5. python flask高级编程之restful_('Python Flask高级编程之RESTFul API前后端分离精讲',),全套视频教程学习资料通过百度云网盘下载...

    资源详情 r n t某课网好评度100%的Python Flask高级编程之RESTFul API前后端分离精讲 r n t t t第1章 随便聊聊 r n t t t聊聊Flask与Django,聊 ...

  6. python画交互式地图_使用Python构建交互式地图-入门指南

    python画交互式地图 Welcome to The Beginner's Guide to Building Interactive Maps in Python 欢迎使用Python构建交互式地 ...

  7. python图片字符分割_图像分割python

    常用的十大 python 图像处理工具 本文为 AI 研习社编译的技术博客,原标题 : 10 Python image manipulation tools. 作者 | Parul Pandey 翻译 ...

  8. python编译器源码_编译python源码

    广告关闭 回望2020,你在技术之路上,有什么收获和成长么?对于未来,你有什么期待么?云+社区年度征文,各种定制好礼等你! 尝试通过源码自己编译 python,使用的系统是 ubuntu14.04 l ...

  9. python彩票数据分析案例_天津Python人工智能课程

    Python人工智能课程介绍 人工智能主要致力于计算机视觉,自然语言处理与语音识别三大领域!其基础与核心都是机器学习,当下AI时代各大行业巨头公司都在争相追逐这些热门领域,创业公司更是层出不穷,人工智 ...

最新文章

  1. mp3 音频 音乐 tag ID3 ID3V1 ID3V2 标签 读取信息 获得图片 jpeg bmp 图片转换(上)
  2. 在ubuntu 16.04下安装gitlab(摘抄中文官方网站)
  3. 打砖块小游戏php程序,利用原生js实现html5打砖块小游戏(代码示例)
  4. spring cloud 入门系列六:使用Zuul 实现API网关服务
  5. HDU 1257 - 最少拦截系统
  6. 2021-07-03图标,选择框
  7. word 无法启动转换器wps32修复工具
  8. calib matlab,toolbox_calib 图片处理,各种用于 的.M文件,非常适 初学者。 matlab 242万源代码下载- www.pudn.com...
  9. NoteExpress 文献管理软件及使用相关问题
  10. PAT考试经验总结(甲乙级均适用)~~想满分的请看这里!~~
  11. 安卓ps2模拟器_安卓PSP模拟器评测:火影忍者究极冲击
  12. Python——实现防止微信撤回消息
  13. Ceph 集群监控之Calamari 安装部署
  14. java.sql.SQLException: No suitable driver found for “jdbc:mysql://localhost:3306/db1“;
  15. 线程状态是五种对?还是六种对?
  16. 企业权限管理系统---用户模块
  17. columns样式 jquery_columns的属性
  18. 葛洲坝地产的“5G科技”演化:三大维度推进,不唯技术控
  19. 信号完整性之串扰仿真(一)
  20. MATLAB 离散傅里叶变换(DFT)、逆离散傅里叶变换(IDFT)、快速傅里叶变换(FFT)的实现

热门文章

  1. Freemaker之代码生成
  2. poj 2152 Fire - 经典树形dp
  3. 互联网公司数据安全保护新探索
  4. android studio avd manager 命令行,avdmanager
  5. 0x80070570文件或目录损坏且无法读取解决方法
  6. python小型登录系统_(Python)注册登录系统完整版
  7. 解决git中upstream丢失问题Your branch is based on 'origin/xxxx', but the upstream is gone.
  8. 基于socket的联机五子棋
  9. 使用CUPS打印服务
  10. 程序员练级(转自酷壳)