Python在游戏中的热更新实现

 更新时间:2021年10月26日 16:02:52   作者:香菜聊游戏  
本文主要介绍了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 热更新内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python中关于面向对象概念的详细讲解

    Python中关于面向对象概念的详细讲解

    要了解面向对象我们肯定需要先知道对象到底是什么玩意儿。关于对象的理解很简单,在我们的身边,每一种事物的存在都是一种对象。总结为一句话也就是:对象就是事物存在的实体
    2021-10-10
  • python3.x 将byte转成字符串的方法

    python3.x 将byte转成字符串的方法

    今天小编就为大家分享一篇python3.x 将byte转成字符串的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 图解python全局变量与局部变量相关知识

    图解python全局变量与局部变量相关知识

    这篇文章主要介绍了图解python全局变量与局部变量相关知识,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • Python实现向列表或数组添加元素

    Python实现向列表或数组添加元素

    Python中的列表是一种动态数组,可以存储不同数据类型的元素,并提供多种方法进行元素的添加和删除,列表是Python中非常灵活和强大的数据结构,可以通过索引访问、修改和操作列表中的元素,列表的创建十分简单,只需使用方括号括起元素,并用逗号分隔
    2024-09-09
  • Python转换itertools.chain对象为数组的方法

    Python转换itertools.chain对象为数组的方法

    这篇文章主要介绍了Python转换itertools.chain对象为数组的方法,通过代码给大家介绍了itertools 的 chain() 方法,需要的朋友可以参考下
    2020-02-02
  • VS Code配置Anaconda Python环境的详细教程

    VS Code配置Anaconda Python环境的详细教程

    在 Visual Studio Code (VS Code) 中可以使用 Anaconda 环境进行 Python 开发,可以充分利用 Anaconda 提供的包管理和虚拟环境功能,同时享受 VS Code 提供的强大开发工具和调试功能,本文主要介绍了VS Code配置Anaconda Python环境的详细教程,需要的朋友可以参考下
    2024-09-09
  • PyTorch一小时掌握之autograd机制篇

    PyTorch一小时掌握之autograd机制篇

    这篇文章主要介绍了PyTorch一小时掌握之autograd机制篇,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • python高级特性和高阶函数及使用详解

    python高级特性和高阶函数及使用详解

    Python很棒,它有很多高级用法值得细细思索,学习使用。这篇文章主要介绍了python高级特性和高阶函数及使用详解,需要的朋友可以参考下
    2018-10-10
  • python 求定积分和不定积分示例

    python 求定积分和不定积分示例

    今天小编就为大家分享一篇python 求定积分和不定积分示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • 如何在keras中添加自己的优化器(如adam等)

    如何在keras中添加自己的优化器(如adam等)

    这篇文章主要介绍了在keras中实现添加自己的优化器(如adam等)方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-06-06

最新评论