Заставить интерпретатор python перезагрузить модуль кода

цикл разработки кода 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)

5 ответов


UPDATE: так как v8 сервер Odoo предоставляет для выполнения этого.

Отличный вопрос, я часто задавался тем же вопросом. Я думаю, что основная проблема с кодом, который вы опубликовали, заключается в том, что он только перезагружает модуль OpenERP __init__.py файл, а не все отдельные файлы. The reimport модуль рекомендован ecatmur позаботится об этом, и мне также пришлось отменить регистрацию анализаторов отчетов модуля и классов моделей перед перезагрузкой всё.

Я разместил свой module_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 {}

на reload функции перезагрузится один модуль. Существуют различные решения для рекурсивной перезагрузки обновленных пакетов; см. как повторно импортировать обновленный пакет в интерпретаторе Python?

часть проблемы заключается в том, что существующие объекты необходимо настроить для ссылки на новые классы и т. д. из перезагруженных модулей;реимпорт Это достаточно хорошо. В консоли IPython соответствовало интерактивные пользуюсь автоматическая перезагрузка расширение, хотя оно не предназначено для использования вне IPython.


ipython имеет модуль deepreload, документация здесь: http://ipython.org/ipython-doc/stable/api/generated/IPython.lib.deepreload.html#module-IPython.lib.deepreload

Я думаю, что это можно использовать за пределами IPython REPL.


Если вы просто занимаетесь разработкой, перезагрузка в порядке, но если вы находитесь в развертывании, вы должны избегать таких трюков, потому что они никогда не будут работать 100% времени. Всегда будут какие-то тонкости, где изменения не будут распространяться. Например, если какой-то код копирует объект, а не просто использует ссылки на него, то после перезагрузки он останется прежним. И наоборот, если ссылка не распространяется вперед правильно, то is сравнение потерпит неудачу, когда это будет ожидается работа, потому что один из объектов будет из" старого " неизданного модуля. Единственный 100% уверенный метод огня - перезагрузить все, что по сути является перезагрузкой сервера.

даже если вы просто занимаетесь разработкой, вы иногда будете сталкиваться с ложными ошибками, которые являются лишь побочными эффектами неполной перезагрузки. Если вам не приходит в голову попробовать чистый перезапуск, вы можете потратить долго время пытается отследить фантомную ошибку. Так что, если ты закончишь ... делая это, держи это в подсознании.


встроенная функция перезагрузки перезагружает модуль или пакет. Однако в контексте OpenERP вам нужно немного больше, так как перезагрузка дополнения OpenERP требует обработки XML-файлов и т. д. Но я согласен, что иметь это в OpenERP было бы неплохо.