Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force python interpreter to reload a code module

Tags:

The OpenERP python code development cycle is to edit your code, restart the server and test it. Restarting the server is necessary, because it's what makes your source code to be reloaded into memory, but it adds an annoying delay in your work pace.

Since python is such a dynamic language, I wonder if there is a way to force a running python interpreter (the app server ) to reload on the fly a code module, so that it can be tested without restarting the app server?

Update: Following down the reload path suggested by @ecatmur, I got the the code below, but it still doesnt work:

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) 
like image 556
Daniel Reis Avatar asked Sep 26 '12 08:09

Daniel Reis


People also ask

How do I force a Python reload module?

The reload() is used to reload a previously imported module or loaded module. This comes handy in a situation where you repeatedly run a test script during an interactive session, it always uses the first version of the modules we are developing, even we have made changes to the code.

How do you refresh code in Python?

To refresh a web page using the selenium module in Python, we use the refresh() function. This is shown in the code below. The refresh() will refresh the web page, acting just like the refresh button of a web browser or clicking the 'F5' button on your keyboard.

How do I restart a Python module?

Instead, to restart a process in Python, you must create a new instance of the process with the same configuration and then call the start() function.

How do I load a Python module?

In Python, modules are accessed by using the import statement. When you do this, you execute the code of the module, keeping the scopes of the definitions so that your current file(s) can make use of these.


2 Answers

The reload built-in function will reload a single module. There are various solutions to recursively reload updated packages; see How to re import an updated package while in Python Interpreter?

Part of the issue is that existing objects need to be adjusted to reference the new classes etc. from the reloaded modules; reimport does this reasonably well. In the IPython interactive console I use the autoreload extension, although it's not designed for use outside IPython.

like image 174
ecatmur Avatar answered Oct 04 '22 09:10

ecatmur


UPDATE: since v8 the Odoo server provides an --auto-reload option to perform this.

Excellent question, I've often wondered the same. I think the main problem with the code you posted is that it only reloads the OpenERP module's __init__.py file, not all the individual files. The reimport module recommended by ecatmur takes care of that, and I also had to unregister the module's report parsers and model classes before reloading everything.

I've posted my module_reload module on Launchpad. It seems to work for changes to model classes, osv_memory wizards, and report parsers. It does not work for old-style wizards, and there may be other scenarios that don't work.

Here's the method that reloads the module.

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 {} 
like image 32
Don Kirkby Avatar answered Oct 04 '22 08:10

Don Kirkby