您现在的位置是:群英 > 开发技术 > Python语言
python怎样实现热更新除了,原理是什么?
Admin发表于 2021-12-13 18:57:571172 次浏览

    这篇文章给大家分享的是Python在游戏中的热更新实现。小编觉得挺实用的,因此分享给大家做个参考,下文介绍了热更新及具体的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热更新有帮助,想要了解更多可以继续浏览群英网络其他相关的文章。

    文本转载自脚本之家

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

    标签: python热更新
    相关信息推荐
    2021-11-20 17:45:43 
    摘要:这篇文章我们来了解python中浅拷贝的实现,python中浅拷贝是对一个对象最顶层的拷贝。,即只拷贝对象的数据内容和父对象,不拷贝对象内部的子对象。下文介绍了四种实现浅拷贝的方式,有需要的朋友可以参考,接下来就跟随小编来了解看看吧!
    2022-11-12 18:03:30 
    摘要:Vue3中如何自定义指令?下面本篇文章就来手把手教大家在 Vue3 中自定义指令,希望对大家有所帮助!
    2022-05-28 17:11:15 
    摘要:java实现九九乘法表的方法:构建两层嵌套的for循环,外层for循环用于控制行,内层for循环用于控制某行上的乘法表达式,每行输出完毕后进行换行即可。
    云活动
    推荐内容
    热门关键词
    热门信息
    群英网络助力开启安全的云计算之旅
    立即注册,领取新人大礼包
    • 联系我们
    • 24小时售后:4006784567
    • 24小时TEL :0668-2555666
    • 售前咨询TEL:400-678-4567

    • 官方微信

      官方微信
    Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
    增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
    免费拨打  400-678-4567
    免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
    微信公众号
    返回顶部
    返回顶部 返回顶部