我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python在游戏中的热更新实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python在游戏中的热更新实现

介绍:

热更新,就是在服务器不重启的的情况下,对游戏增加新的功能或者修复出现bug 的代码。游戏更新迭代速度快,催生了热更技术的需求,在我经历过的游戏项目中,无论是服务端还是客户端,版本的更新都是围绕着热更新,特别是现在游戏动辄几个G,每次让玩家下载完整的包不现实,随意游戏必须要支持热更。下面来谈一下客户端Python热更新的处理。

原理:

1.标准import

都知道Python提供了import可以导入一个标准的python模块,将模块载入内存,并加到sys.modules中。但是多次import同一模块只是将名称导入到当前的Local名字空间,也就是一个模块不会重复载入,所以想要热更靠这个特性是不行的。此路不通,请换个思路。

2.reload函数

reload()函数可以重新载入已经导入的模块,这样似乎就可以热更新Python的代码了。但是python原生的reload函数太过简单,不足以支撑游戏的热更新需求,主要原因有几个: reload重新加载的模块不会替换旧版本的模块,也就是已经引用的旧模块无法更新 同样因为不能旧对象的引用,使用from ... import ... 方式引用的模块同样不能更新 reloas(m)后,class及其派生class的实例对象,仍然使用旧的class定义。 同时加载模块失败时候,没有回滚机制,导致需要重新import该模块 因此,结合游戏的热更新需求,自定义合适的reload。新的自定义reload目的是为了达到在原程序不结束的情况下,让程序能动态加载改动后的代码。主要想达到下面两点: 提升开发效率 在游戏不重启的情况下修复紧急BUG

实现:

热更新最核心的需求就是让python解释器执行最新的代码,同时保证其他关联模块不会出现问题。对于刷新function,class内定义的method比较容易实现,但对于刷新module内定义的变量,class内定义的变量,还有新增加的成员变量,则需要有统一的约定。所以在实现热更新过程中,我们需要考虑好代码更新和数据更新这两点,下面罗列一下新的reload具备哪些特性:

1.更新代码定义(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)

2.替换类的内容


# 用新类内容更新旧类内容,保持旧类本身地址不变  
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()

3.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)

4.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.runLogic()      # 新修复的逻辑

总结:

只是在基础的reload模块上做了一些定制,让热更新更适合游戏的开发节奏,而不是简单暴力的reload模块

到此这篇关于Python在游戏中的热更新实现的文章就介绍到这了,更多相关Python 热更新内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python在游戏中的热更新实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python在游戏中如何进行热更新处理

小编给大家分享一下Python在游戏中如何进行热更新处理,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!原理:1.标准import都知道Python提供了import可以导入一个标准的python模块,将模块载入内存,并加到
2023-06-25

详解Android中实现热更新的原理

这篇文章就来介绍一下Android中实现热更新的原理。 一、ClassLoader 我们知道Java在运行时加载对应的类是通过ClassLoader来实现的,ClassLoader本身是一个抽象来,Android中使用PathClassLo
2022-06-06

如何在.Net Core中实现选择数据热更新

本篇文章为大家展示了如何在.Net Core中实现选择数据热更新,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。实践 通过AddSingleton单例方式注入,然后使用 IOptionsMonitor
2023-06-06

uniapp实现app热更新的方法

本文主要介绍了uniapp实现app热更新的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-01-03

uniapp开发APP之强制更新和热更新的实现

使用uni-app开发,可将代码编译到iOS、Android、微信小程序等多个平台,升级时也需考虑多平台同步升级,下面这篇文章主要给大家介绍了关于uniapp开发APP之强制更新和热更新的相关资料,需要的朋友可以参考下
2022-12-21

python中的热更新或动态加载

遍览网络中关于动态加载模块的文章,发现有两种方法,一种是用守护进程的方法,一种是用python自带的reload函数。比较靠谱的文章是如下两篇:https://my.oschina.net/1123581321/blog/168720htt
2023-01-31

ElasticSearch的滚动更新在Python中如何实现?(Python环境下,ElasticSearch滚动更新的实现步骤?)

Elasticsearch滚动更新允许在不中断服务的情况下更新集群。在Python中实现滚动更新的步骤包括:初始化Elasticsearch客户端。创建索引模板,定义新索引的设置和映射。创建新索引,使用模板中的设置和映射。重新索引数据,将数据从旧索引转移到新索引。交换别名,使应用程序使用新索引。删除旧索引。重复步骤3-6更新其他索引分片。注意:在重新索引期间,确保源索引和目标索引的映射兼容,并监控滚动更新过程,以确保顺利进行。
ElasticSearch的滚动更新在Python中如何实现?(Python环境下,ElasticSearch滚动更新的实现步骤?)
2024-04-02

怎么在python中使用tkinter实现一个扫雷游戏

怎么在python中使用tkinter实现一个扫雷游戏?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实现代码# 导入所需库from tkinter import
2023-06-15

uniApp实现热更新的思路与详细过程

经常在做app的时候,会有做热更新的需求,这也是常用的更新app的一种手段,下面这篇文章主要给大家介绍了关于uniApp实现热更新的思路与详细过程,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2022-11-16

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录