开发环境中,自动重启Openerp-Server的方法
-
在开发的时候,因为不停的修改代码(py文件),经常需要重启Openerp-Server。
借鉴了以前的项目,写了一个小方法让程序自启动,抛砖引玉之用。
Step 1, 在/openerp-server/openerp/tools/ 目录下添加 autoreload.py。代码如下:<br /><br /># Autoreloading launcher.<br /># Borrowed from Peter Hunt and the CherryPy project (http://www.cherrypy.org).<br /># Some taken from Ian Bicking's Paste (http://pythonpaste.org/).<br /># Adjustments made by Michael Elsdoerfer ([email protected]).<br />#<br /># Portions copyright (c) 2004, CherryPy Team ([email protected])<br /># All rights reserved.<br />#<br /># Redistribution and use in source and binary forms, with or without modification,<br /># are permitted provided that the following conditions are met:<br />#<br /># * Redistributions of source code must retain the above copyright notice,<br /># this list of conditions and the following disclaimer.<br /># * Redistributions in binary form must reproduce the above copyright notice,<br /># this list of conditions and the following disclaimer in the documentation<br /># and/or other materials provided with the distribution.<br /># * Neither the name of the CherryPy Team nor the names of its contributors<br /># may be used to endorse or promote products derived from this software<br /># without specific prior written permission.<br />#<br /># THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND<br /># ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED<br /># WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE<br /># DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE<br /># FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL<br /># DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR<br /># SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER<br /># CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,<br /># OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE<br /># OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.<br /><br />import os, sys, time<br /><br />try:<br /> import thread<br />except ImportError:<br /> import dummy_thread as thread<br /><br /># This import does nothing, but it's necessary to avoid some race conditions<br /># in the threading module. See http://code.djangoproject.com/ticket/2330 .<br />try:<br /> import threading<br />except ImportError:<br /> pass<br /><br /><br />RUN_RELOADER = True<br /><br />_mtimes = {}<br />_win = (sys.platform == "win32")<br /><br />def code_changed():<br /> global _mtimes, _win<br /> for filename in filter(lambda v: v, map(lambda m: getattr(m, "__file__", None), sys.modules.values())):<br /> if filename.endswith(".pyc") or filename.endswith(".pyo"):<br /> filename = filename[:-1]<br /> if not os.path.exists(filename):<br /> continue # File might be in an egg, so it can't be reloaded.<br /> stat = os.stat(filename)<br /> mtime = stat.st_mtime<br /> if _win:<br /> mtime -= stat.st_ctime<br /> if filename not in _mtimes:<br /> _mtimes[filename] = mtime<br /> continue<br /> if mtime != _mtimes[filename]:<br /> _mtimes = {}<br /> return True<br /> return False<br /><br />def reloader_thread(softexit=False):<br /> """If ``soft_exit`` is True, we use sys.exit(); otherwise ``os_exit``<br /> will be used to end the process.<br /> """<br /> while RUN_RELOADER:<br /> if code_changed():<br /> # force reload<br /> if softexit:<br /> sys.exit(3)<br /> else:<br /> os._exit(3)<br /> time.sleep(1)<br /><br />def restart_with_reloader():<br /> while True:<br /> args = [sys.executable] + sys.argv<br /> if sys.platform == "win32":<br /> args = ['"%s"' % arg for arg in args]<br /> new_environ = os.environ.copy()<br /> new_environ["RUN_MAIN"] = 'true'<br /> exit_code = os.spawnve(os.P_WAIT, sys.executable, args, new_environ)<br /> if exit_code != 3:<br /> return exit_code<br /><br />def python_reloader(main_func, args, kwargs, check_in_thread=True):<br /> """<br /> If ``check_in_thread`` is False, ``main_func`` will be run in a separate<br /> thread, and the code checker in the main thread. This was the original<br /> behavior of this module: I (Michael Elsdoerfer) changed the default<br /> to be the reverse: Code checker in thread, main func in main thread.<br /> This was necessary to make the thing work with Twisted<br /> (http://twistedmatrix.com/trac/ticket/4072).<br /> """<br /> if os.environ.get("RUN_MAIN") == "true":<br /> if check_in_thread:<br /> thread.start_new_thread(reloader_thread, (), {'softexit': False})<br /> else:<br /> thread.start_new_thread(main_func, args, kwargs)<br /><br /> try:<br /> if not check_in_thread:<br /> reloader_thread(softexit=True)<br /> else:<br /> main_func(*args, **kwargs)<br /> except KeyboardInterrupt:<br /> pass<br /> else:<br /> try:<br /> sys.exit(restart_with_reloader())<br /> except KeyboardInterrupt:<br /> pass<br /><br />def jython_reloader(main_func, args, kwargs):<br /> from _systemrestart import SystemRestart<br /> thread.start_new_thread(main_func, args)<br /> while True:<br /> if code_changed():<br /> raise SystemRestart<br /> time.sleep(1)<br /><br /><br />def main(main_func, args=None, kwargs=None, **more_options):<br /> if args is None:<br /> args = ()<br /> if kwargs is None:<br /> kwargs = {}<br /> if sys.platform.startswith('java'):<br /> reloader = jython_reloader<br /> else:<br /> reloader = python_reloader<br /> reloader(main_func, args, kwargs, **more_options)<br /><br />
Step 2,在 /openerp-server/openerp/tools/init.py 中导出:<br /><br />.....<br /><br />from autoreload import main as autoreload_main<br /><br />.....<br /><br />
Step 3, 加入启动代码: /openerp-server/openerp-server 文件<br />if __name__ == "__main__":<br /> .......<br /> openerp.tools.autoreload_main(openerp.cli.main)<br /> <br />
-
杨兄大作学习了 ~
我这里也写了一个脚本,托管在 https://github.com/buke/autoreload br />
与杨兄实现方法不同的地方是:
1、采取 popen 开启OE进程,可适用于 OE 7 开启 workers 参数启用多进程的情况
2、无需对 OE 源码修改,只需要把OE 执行脚本作为参数即可。如 $ ./autoreload "openerp-server -c openerp-server.conf" (windows 请执行 python autoreload "python openerp-server -c openerp-server.conf")
更多请移步本人博客 [检测到链接无效,已移除]
欢迎指正! -
Update:
linux 下使用 inotify 事件通知机制,抛弃丑陋的定时轮询。
代码已同步到 https://github.com/buke/autoreload br />
详情请查看本人博客 http://buke.github.io/blog/2013/07/01/using-inotify-detected-python-source-file-and-autoreload-process/