Forcer l'interpréteur python à recharger un module de code
le cycle de développement de code Python OpenERP consiste à éditer votre code, redémarrer le serveur et le tester. Redémarrer le serveur est nécessaire, car c'est ce qui fait que votre code source doit être rechargé en mémoire, mais cela ajoute un retard gênant dans votre rythme de travail.
étant donné que python est un langage dynamique, je me demande s'il y a un moyen de forcer un interpréteur Python en cours d'exécution (le serveur app ) à recharger à la volée un module de code, de sorte qu'il puisse être testé sans redémarrer le serveur d'application?
mise à Jour:
En suivant le chemin reload
suggéré par @ecatmur, j'ai obtenu le code ci-dessous, mais il ne fonctionne toujours pas:
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 réponses
mise à JOUR: depuis le v8 Odoo server fournit un --auto-reload
option pour effectuer cette.
excellente question, je me suis souvent demandé la même chose. Je pense que le principal problème avec le code que vous avez posté est qu'il ne recharge que le fichier __init__.py
du module OpenERP, pas tous les fichiers individuels. Le module reimport
recommandé par ecatmur s'occupe de cela, et j'ai également dû désinscrire Les analyseurs de rapport du module et les classes de modèles avant de tout recharger.
j'ai posté mon module module_reload
sur Launchpad . Il semble fonctionner pour les changements aux classes de modèle, osv_memory
magiciens, et les analyseurs de rapport. Il ne fonctionne pas pour les sorciers de l'ancien style, et il peut y avoir d'autres scénarios qui ne fonctionnent pas.
Voici la méthode qui recharge le 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 {}
la fonction intégrée reload
rechargera un seul module. Il existe diverses solutions pour recharger de façon récursive les paquets mis à jour; voir comment réimporter un paquet mis à jour alors qu'il est dans L'interpréteur Python?
une partie du problème réside dans le fait que les objets existants doivent être ajustés pour faire référence aux nouvelles classes, etc. des modules rechargés; reimport fait raisonnablement bien. In the IPython console interactive j'utilise l'extension autoreload , bien qu'elle ne soit pas conçue pour une utilisation en dehors D'IPython.
ipython dispose d'un module de chargement en profondeur, la documentation est ici: http://ipython.org/ipython-doc/stable/api/generated/IPython.lib.deepreload.html#module-IPython.lib.deepreload
je pense qu'il est utilisable en dehors de l'ipython REPL.
si vous ne faites que du développement, alors rechargez est OK, mais si vous êtes en déploiement, vous devriez éviter ces trucs, parce qu'ils ne fonctionneront jamais à 100% du temps. Il y aura toujours des subtilités, où les changements ne se propageront pas. Par exemple, si un code copie un objet au lieu de simplement utiliser des références, il restera le même après le rechargement. À l'inverse, si une référence ne se propage pas correctement vers l'avant, alors une comparaison is
échouera quand elle être appelés à travailler, parce que l'un des objets de la "vieille" unreleased module. Le seul 100% sûre méthode pour recharger tout, ce qui est, essentiellement, un redémarrage du serveur est.
même si vous ne faites que du développement, vous rencontrerez occasionnellement de faux bogues qui ne sont que les effets secondaires d'un rechargement incomplet. S'il ne vous vient pas à l'esprit d'essayer un redémarrage propre, vous pouvez passer un long temps à essayer de suivre le bogue fantôme vers le bas. Donc si tu finis par faire ça, garde ça en tête.
la fonction de recharge intégrée Recharge un module ou un paquet. Dans le contexte D'OpenERP cependant, vous avez besoin d'un peu plus, car recharger un addon OpenERP nécessite le traitement des fichiers XML, etc. Mais je suis d'accord sur le fait que ce serait bien d'avoir ça à OpenERP.