Odoo自动重载python文件

在Odoo模块开发时,每一次的python代码的更改都要进行Odoo服务的重启。下面介绍一个小技巧用来代替频繁的在命令行下ctrl+c 手工重启.

介绍

Odoo服务的启动,离不开odoo-bin.py这个入口文件。今天的小技巧就在这里。 在Odoo的开发过程中,我们通常使用odoo-bin启动一个本地odoo服务。odoo-bin命令可以跟随很多参数。我们使用--help来查看一下(内容太长,省略一些)

Usage: odoo-bin [options]

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit

  Common options:
    -c CONFIG, --config=CONFIG
                        specify alternate config file
...
...
  Advanced options:
    --dev=DEV_MODE      Enable developer mode. Param: List of options
                        separated by comma. Options : all,
                        [pudb|wdb|ipdb|pdb], reload, qweb, werkzeug, xml
...
...

看到上面的--dev=DEV_MODE参数没。诀窍就在这里。使用--dev=all就能在python代码改变时候自动重载odoo服务,而且xml视图文件的更改也会立即更新,不需要再跑到【应用】中手工升级修改过视图的对应模块。


必要安装

要启用自动重载功能首先需要安装watchdog这个python库.

$ pip3 install watchdog

简单原理

其实自动重载python代码的原理就是利用watchdog监控模块所在目录下的文件系统事件,当文件内容修改时,会触发FileModifiedEvent。Odoo目录下/odoo/service/server.py文件129行进行了自动重启服务处理。

class FSWatcher(object):
    def __init__(self):
        self.observer = Observer()
        for path in odoo.modules.module.ad_paths:
            _logger.info('Watching addons folder %s', path)
            self.observer.schedule(self, path, recursive=True)

    def dispatch(self, event):
        if isinstance(event, (FileCreatedEvent, FileModifiedEvent, FileMovedEvent)):
            if not event.is_directory:
                path = getattr(event, 'dest_path', event.src_path)
                if path.endswith('.py') and not os.path.basename(path).startswith('.~'):
                    try:
                        source = open(path, 'rb').read() + b'\n'
                        compile(source, path, 'exec')
                    except FileNotFoundError:
                        _logger.error('autoreload: python code change detected, FileNotFound for %s', path)
                    except SyntaxError:
                        _logger.error('autoreload: python code change detected, SyntaxError in %s', path)
                    else:
                        if not getattr(odoo, 'phoenix', False):
                            _logger.info('autoreload: python code updated, autoreload activated')
                            restart()