Python在游戲中的熱更新實現(xiàn)
介紹:
熱更新,就是在服務器不重啟的的情況下,對游戲增加新的功能或者修復出現(xiàn)bug 的代碼。游戲更新迭代速度快,催生了熱更技術的需求,在我經(jīng)歷過的游戲項目中,無論是服務端還是客戶端,版本的更新都是圍繞著熱更新,特別是現(xiàn)在游戲動輒幾個G,每次讓玩家下載完整的包不現(xiàn)實,隨意游戲必須要支持熱更。下面來談一下客戶端Python熱更新的處理。
原理:
1.標準import
都知道Python提供了import可以導入一個標準的python模塊,將模塊載入內(nèi)存,并加到sys.modules中。但是多次import同一模塊只是將名稱導入到當前的Local名字空間,也就是一個模塊不會重復載入,所以想要熱更靠這個特性是不行的。此路不通,請換個思路。
2.reload函數(shù)
reload()函數(shù)可以重新載入已經(jīng)導入的模塊,這樣似乎就可以熱更新Python的代碼了。但是python原生的reload函數(shù)太過簡單,不足以支撐游戲的熱更新需求,主要原因有幾個: reload重新加載的模塊不會替換舊版本的模塊,也就是已經(jīng)引用的舊模塊無法更新 同樣因為不能舊對象的引用,使用from ... import ... 方式引用的模塊同樣不能更新 reloas(m)后,class及其派生class的實例對象,仍然使用舊的class定義。 同時加載模塊失敗時候,沒有回滾機制,導致需要重新import該模塊 因此,結合游戲的熱更新需求,自定義合適的reload。新的自定義reload目的是為了達到在原程序不結束的情況下,讓程序能動態(tài)加載改動后的代碼。主要想達到下面兩點: 提升開發(fā)效率 在游戲不重啟的情況下修復緊急BUG
實現(xiàn):
熱更新最核心的需求就是讓python解釋器執(zhí)行最新的代碼,同時保證其他關聯(lián)模塊不會出現(xiàn)問題。對于刷新function,class內(nèi)定義的method比較容易實現(xiàn),但對于刷新module內(nèi)定義的變量,class內(nèi)定義的變量,還有新增加的成員變量,則需要有統(tǒng)一的約定。所以在實現(xiàn)熱更新過程中,我們需要考慮好代碼更新和數(shù)據(jù)更新這兩點,下面羅列一下新的reload具備哪些特性:
1.更新代碼定義(function/method/static_method/class_method) 不更新數(shù)據(jù)(除了代碼定義外的類型都當作是數(shù)據(jù)) 在module中約定reload_module接口,class中約定reload_class接口,在這兩個接口中手動處理數(shù)據(jù)的更新,還有更多的約定和接口待完成 替換函數(shù)對象的內(nèi)容
# 用新的函數(shù)對象內(nèi)容更新舊的函數(shù)對象中的內(nèi)容,保持函數(shù)對象本身地址不變 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.替換類的內(nèi)容
# 用新類內(nèi)容更新舊類內(nèi)容,保持舊類本身地址不變 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的內(nèi)容,所以不用再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接口,可以自定義數(shù)據(jù)的更新。 下面添加一些用例:
def x_reload_class(self): """ 熱更新后,每個重新對象的實例都會執(zhí)行這個函數(shù) 由于新老對象的替換不會重新調用構造函數(shù),因此有必要對熱更新的類對象執(zhí)行初始化邏輯 處理新老變量的修復,函數(shù)執(zhí)行環(huán)境的修復 """ self._new_var = 5000 # 新變量的初始化 self.runLogic() # 新修復的邏輯
總結:
只是在基礎的reload模塊上做了一些定制,讓熱更新更適合游戲的開發(fā)節(jié)奏,而不是簡單暴力的reload模塊
到此這篇關于Python在游戲中的熱更新實現(xiàn)的文章就介紹到這了,更多相關Python 熱更新內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python執(zhí)行scp命令拷貝文件及文件夾到遠程主機的目錄方法
今天小編就為大家分享一篇python執(zhí)行scp命令拷貝文件及文件夾到遠程主機的目錄方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07Python爬蟲實現(xiàn)的根據(jù)分類爬取豆瓣電影信息功能示例
這篇文章主要介紹了Python爬蟲實現(xiàn)的根據(jù)分類爬取豆瓣電影信息功能,結合完整實例形式分析了Python針對電影信息分類抓取的相關實現(xiàn)技巧,需要的朋友可以參考下2019-09-09Pytorch實現(xiàn)將label變成one hot編碼的兩種方式
這篇文章主要介紹了Pytorch實現(xiàn)將label變成one hot編碼的兩種方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02詳解使用Selenium爬取豆瓣電影前100的愛情片相關信息
這篇文章主要介紹了詳解使用Selenium爬取豆瓣電影前100的愛情片相關信息,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03Python3標準庫之dbm UNIX鍵-值數(shù)據(jù)庫問題
dbm是面向DBM數(shù)據(jù)庫的一個前端,DBM數(shù)據(jù)庫使用簡單的字符串值作為鍵來訪問包含字符串的記錄。這篇文章主要介紹了Python3標準庫:dbm UNIX鍵-值數(shù)據(jù)庫的相關知識,需要的朋友可以參考下2020-03-03Python使用Opencv打開筆記本電腦攝像頭報錯解問題及解決
這篇文章主要介紹了Python使用Opencv打開筆記本電腦攝像頭報錯解問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06