2

データベースからPythonバイトコード(コンパイルされたPythonコード)を動的にロードするために、インポートフック( PEP 302に基づく)を作成しました。

import dyn_imports.test   #@UnresolvedImport

これは正常に機能しますが、モジュールを変更してモジュールをリロードすると、モジュールはリロードされますが、変更が表示されません。

これが私がバイトコードを作成する方法です:

code_object = compile(db.Text(dyn.py_source).encode(), dyn.name.encode(), 'exec')
key_name = 'dyn_imports.' + name
dynmod = models.Dynmods(key_name = key_name, name = key_name, bytecode = db.Blob(marshal.dumps(code_object)))
dynmod.put()
reload(sys.modules[key_name])             # reload the updated code

reload()は、インポートフックのload_module部分を実行します。
これは、インポートフッククラスのload_module関数の簡略化されたバージョンです。

def load_module(self, mod_name):
    mod = imp.new_module(mod_name)
    mod.__loader__ = self
    dynmod = models.Dynmods.get_by_key_name(mod_name)    # load from DB
    mod.__file__ = mod_name
    exec marshal.loads(db.Blob(dynmod.bytecode)) in mod.__dict__
    sys.modules[mod_name] = mod
    return mod

インスタンスをシャットダウンすると、正常に動作します。

更新:バイトコードの代わりにpyソースを使用してインポートローダーもテストしました。これもうまくいきませんでした。私は開発サーバーでほとんどのテストを行いました。

以前にJinja2モジュールローダーを作成しました。これは、データストアからJinjaコンパイル済みテンプレート(= pyソース)をロードします。Jinja環境を再作成し、sys.modulesからモジュール(コンパイルされたテンプレート)を削除すると、インスタンスを再起動せずに、新しいモジュールが再ロードされます。それで、私はここで何を間違っているのですか?

4

1 に答える 1

0

私は解決策を見つけました。変更されたモジュールをリロードすることに加えて、このモジュールを使用(インポート)するすべてのモジュールをリロードする必要があります。私はいくつかのテストを行いましたが、正常に動作します。正しい順序も重要です。そこで、インポート依存関係グラフを作成し、それを使用してモジュールをリロードする方法を理解する必要があります。

しかし、それは新しい質問です。

モジュールが動的モジュールをインポートするときに、依存関係のリストを作成します。このリストを使用して、依存モジュールをリロードできます。また、GAEappidの他のインスタンスにフラグを立てる必要があります。これらの他のインスタンスは、フラグが立てられた動的モジュール(使用されている場合)をリロードし、この他のインスタンスの動的モジュールの依存モジュールをリロードする必要があります。

すべてのインスタンスに一意のインスタンスIDを作成するために、クラス変数を追加しました。

instance = datetime.datetime.utcnow()

インポートフッククラスに。Memcacheは、他のインスタンスにフラグを立てるためにsetterインスタンスによって使用されます。このフラグには、リロードされた動的モジュールごとに、動的モジュールのフラグセッターインスタンスとリロード日時スタンプが含まれます。他の(フラグゲッター)インスタンスは、動的モジュールをリロードする必要があるかどうかを確認できます。

于 2012-11-27T07:01:04.617 に答える