データベースから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からモジュール(コンパイルされたテンプレート)を削除すると、インスタンスを再起動せずに、新しいモジュールが再ロードされます。それで、私はここで何を間違っているのですか?