2

我创建了一个导入钩子(基于PEP 302),以从数据库中动态加载 python 字节码(编译后的 python 代码)。

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

我找到了解决方案。除了重新加载更改的模块外,我还必须重新加载所有使用(导入)此模块的模块。我做了一些测试,效果很好。正确的顺序也很重要。所以现在我必须弄清楚,如何创建一个导入依赖图并使用它来重新加载模块。

但这是一个新问题。

当模块导入动态模块时,我会创建一个依赖项列表。使用这个列表,我可以重新加载依赖模块。我还必须标记我的 GAE appid 的其他实例。这些其他实例必须重新加载标记的动态模块(如果使用)并重新加载该其他实例中动态模块的依赖模块。

为了为每个实例创建唯一的实例 ID,我添加了类变量:

instance = datetime.datetime.utcnow()

到导入钩子类。setter 实例使用 Memcache 来标记其他实例。此标志包含每个重新加载的动态模块:标志设置器实例和动态模块的重新加载日期时间戳。其他(标志获取器)实例可以检查是否必须重新加载动态模块。

于 2012-11-27T07:01:04.617 回答