クライアントpythonホットアップデート
4130 ワード
紹介:
ホット・アップデートとは、サービスを継続的に維持する場合に、ソフトウェア・コードの論理または構成データを更新修復することです.ゲームプロジェクトにスクリプト言語が導入されるにつれて、ホット更新技術は徐々に標準化され、私が経験したゲームプロジェクトでは、サービス側でもクライアント側でも、バージョンの更新反復は静的patchと動的patch(ホット更新)をめぐって行われています.クライアントPythonのホットアップデートの処理についてお話しします.
原理:標準import標準pythonモジュールをインポートし、モジュールをメモリにロードしsysに追加できることを知っています.modulesで.複数のimport同じモジュールは、現在のLocal名前空間に名前をインポートするだけで、1つのモジュールは重複してロードされません. reload関数reload()関数は、インポートしたモジュールを再ロードすることができ、pythonモジュールを熱的に更新できるように見えます.残念なことに、pythonオリジナルのreload関数はゲームのホット更新の問題をはるかに満たすことができません.なぜなら、reloadが再ロードされたモジュールは古いバージョンのモジュールを削除しません.つまり、すでに参照されている古いモジュールは更新できません.同じように古いオブジェクトの参照ができないため、fromを使用します.import ... 方式で参照されるモジュールはreloas(m)を更新することができなくなった後も、classとその派生classのインスタンスオブジェクトは、古いclass定義を使用します.モジュールのロードに失敗した場合,rollbackメカニズムがなく,モジュールを再importする必要があるため,ゲームのシナリオと結びつけて適切なreloadをカスタマイズする必要がある.新しいカスタムreloadの目的は、元のプログラムが終了しない場合に、変更後のコードを動的にロードできるようにすることです.主に以下の2点に達したい: 開発期間の開発効率を向上させる ゲームを再起動することなく緊急BUG を修復する
実装:
ホットアップデートでは,作成したオブジェクトに新しいコードの変化をどのように獲得させるか,reload前後でタイプの不一致を生じさせないかが実際のポイントである.functionをリフレッシュすると、class内で定義されたmethodが実現しやすいが、module内で定義された変数をリフレッシュするには、class内で定義された変数、さらに新しく追加されたメンバー変数については、統一的な約束が必要である.したがって,ホット更新の過程で,コード更新とデータ更新の2点を考慮すれば,更新は可能である.次は、新しいreloadがどのような特性を備えているかを示します.更新コード定義(function/method/static_method/class_method) はデータを更新(コード定義以外のタイプはデータとみなす) である. moduleでreload_を約束moduleインタフェース、classでreload_を約束classインタフェース、この2つのインタフェースでデータの更新を手動で処理し、さらに多くの約束とインタフェースが完了する 関数オブジェクトの内容を置換
クラスの内容を置換
staticmethod
classmethod
モジュールの更新も似ていて、いちいち貼らないで、ただ元のreloadの基礎の上で改良を行って、モジュールの熱い更新に対して、また1つのreload_を約束しましたmoduleインタフェースで、データの更新をカスタマイズできます.次に、いくつかの例を追加します.
現在のホット更新モジュールは開発デバッグで使用されており、いくつかの更新タスクを簡単に完了することができますが、リモートクライアントに更新するには、閉パッケージ、内部ローカル変数など、より多くの規範とインタフェースが必要であり、徐々に学習と改善が必要です.
ホット・アップデートとは、サービスを継続的に維持する場合に、ソフトウェア・コードの論理または構成データを更新修復することです.ゲームプロジェクトにスクリプト言語が導入されるにつれて、ホット更新技術は徐々に標準化され、私が経験したゲームプロジェクトでは、サービス側でもクライアント側でも、バージョンの更新反復は静的patchと動的patch(ホット更新)をめぐって行われています.クライアントPythonのホットアップデートの処理についてお話しします.
原理:
実装:
ホットアップデートでは,作成したオブジェクトに新しいコードの変化をどのように獲得させるか,reload前後でタイプの不一致を生じさせないかが実際のポイントである.functionをリフレッシュすると、class内で定義されたmethodが実現しやすいが、module内で定義された変数をリフレッシュするには、class内で定義された変数、さらに新しく追加されたメンバー変数については、統一的な約束が必要である.したがって,ホット更新の過程で,コード更新とデータ更新の2点を考慮すれば,更新は可能である.次は、新しいreloadがどのような特性を備えているかを示します.
# ,
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の基礎の上で改良を行って、モジュールの熱い更新に対して、また1つのreload_を約束しましたmoduleインタフェースで、データの更新をカスタマイズできます.次に、いくつかの例を追加します.
def x_reload_class(self):
""" ,
,
,
"""
self._new_var = 5000 #
self.init_widget() #
現在のホット更新モジュールは開発デバッグで使用されており、いくつかの更新タスクを簡単に完了することができますが、リモートクライアントに更新するには、閉パッケージ、内部ローカル変数など、より多くの規範とインタフェースが必要であり、徐々に学習と改善が必要です.