22

OpenERP python代码开发周期是编辑你的代码,重启服务器并测试它。重新启动服务器是必要的,因为它会使您的源代码重新加载到内存中,但它会增加您工作节奏的恼人延迟。

由于 python 是一种动态语言,我想知道是否有一种方法可以强制正在运行的 python 解释器(应用程序服务器)动态重新加载代码模块,以便可以在不重新启动应用程序服务器的情况下对其进行测试?

更新: 按照reload@ecatmur 建议的路径,我得到了下面的代码,但它仍然不起作用:

class module(osv.osv):
    _inherit = "ir.module.module"

    def action_reload(self, cr, uid, ids, context=None):
        for obj in self.browse(cr, uid, ids, context=context):
            modulename = 'openerp.addons.' + obj.name
            tmp = __import__(modulename)
            pycfile = tmp.__file__
            modulepath = string.replace(pycfile, ".pyc", ".py")
            code=open(modulepath, 'rU').read()
            compile(code, modulename, "exec")
            execfile(modulepath)
            reload( sys.modules[modulename] )
        openerp.modules.registry.RegistryManager.delete(cr.dbname)
        openerp.modules.registry.RegistryManager.new(cr.dbname)
4

5 回答 5

14

reload内置函数将重新加载单个模块。有多种解决方案可以递归地重新加载更新的包;请参阅如何在 Python 解释器中重新导入更新的包?

部分问题是需要调整现有对象以从重新加载的模块中引用新类等;reimport做得相当好。在 IPython 交互式控制台中,我使用了autoreload扩展,尽管它不是为在 IPython 之外使用而设计的。

于 2012-09-26T08:12:35.057 回答
9

更新:从 v8 开始,Odoo 服务器提供了一个--auto-reload选项来执行此操作。

很好的问题,我经常想知道同样的问题。我认为您发布的代码的主要问题是它只重新加载 OpenERP 模块的__init__.py文件,而不是所有单个文件。ecatmurreimport推荐的模块可以解决这个问题,我还必须在重新加载所有内容之前取消注册模块的报告解析器和模型类。

我已经在Launchpadmodule_reload上发布了我的模块。它似乎适用于模型类、向导和报告解析器的更改。它不适用于旧式向导,可能还有其他场景不起作用。osv_memory

这是重新加载模块的方法。

def button_reload(self, cr, uid, ids, context=None):
    for module_record in self.browse(cr, uid, ids, context=context):
        #Remove any report parsers registered for this module.
        module_path = 'addons/' + module_record.name
        for service_name, service in Service._services.items():
            template = getattr(service, 'tmpl', '')
            if template.startswith(module_path):
                Service.remove(service_name)

        #Remove any model classes registered for this module
        MetaModel.module_to_models[module_record.name] = []                    

        #Reload all Python modules from the OpenERP module's directory.
        modulename = 'openerp.addons.' + module_record.name
        root = __import__(modulename)
        module = getattr(root.addons, module_record.name)

        reimport(module)
    RegistryManager.delete(cr.dbname)
    RegistryManager.new(cr.dbname)
    return {}
于 2012-10-04T19:28:12.597 回答
1

ipython 有一个 deepreload 模块,文档在这里:http: //ipython.org/ipython-doc/stable/api/generated/IPython.lib.deepreload.html#module-IPython.lib.deepreload

我认为它可以在 ipython REPL 之外使用。

于 2012-10-02T09:54:27.650 回答
1

如果你只是在做开发,那么重新加载是可以的,但如果你在部署中,你应该避免这样的技巧,因为它们永远不会 100% 工作。总会有一些微妙之处,这些变化不会传播。例如,如果某些代码复制一个对象而不是仅使用对它的引用,那么在重新加载后它将保持不变。相反,如果一个引用没有正确地向前传播,那么is当预期它可以工作时,比较就会失败,因为其中一个对象将来自“旧的”未发布的模块。唯一 100% 确定的触发方法是重新加载所有内容,这本质上就是服务器重启。

即使您只是在进行开发,您偶尔也会遇到错误的错误,这些错误只是不完全重新加载的副作用。如果您没有尝试干净重启,您可能会花费很长时间来尝试追踪幻影错误。因此,如果您最终这样做,请记住这一点。

于 2012-10-03T19:04:46.917 回答
0

reload 内置函数重新加载模块或包。但是,在 OpenERP 的上下文中,您需要更多,因为重新加载 OpenERP 插件需要处理 XML 文件等。但我同意在 OpenERP 中使用它会很好。

于 2012-09-26T09:27:18.853 回答