强制python解释器重新加载代码模块

时间:2012-09-26 08:01:41

标签: python openerp

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

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

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

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)

5 个答案:

答案 0 :(得分:14)

reload内置函数将重新加载单个模块。递归重新加载更新的包有各种解决方案;见How to re import an updated package while in Python Interpreter?

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

答案 1 :(得分:9)

更新:自v8以来,Odoo服务器提供--auto-reload选项来执行此操作。

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

我已将module_reload模块发布在Launchpad上。它似乎适用于模型类,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 {}

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

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

即使您正在进行开发,您偶尔也会遇到错误的错误,这些错误只是不完整重新加载的副作用。如果您没有尝试干净重启,则可以花费时间尝试跟踪幻像错误。因此,如果您最终这样做,请将其保留在您的脑海中。

答案 4 :(得分:0)

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