跳转至内容
  • 版块
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(Flatly)
  • 不使用皮肤
折叠

Odoo 中文社区

  1. 主页
  2. 版块
  3. Odoo 开发与实施交流
  4. 开发环境中,自动重启Openerp-Server的方法

开发环境中,自动重启Openerp-Server的方法

已定时 已固定 已锁定 已移动 Odoo 开发与实施交流
7 帖子 3 发布者 8.4k 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • D 离线
    D 离线
    d_yang
    写于 最后由 编辑
    #1

    在开发的时候,因为不停的修改代码(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&#039;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 />#&nbsp; &nbsp;  * Redistributions of source code must retain the above copyright notice,<br />#&nbsp; &nbsp; &nbsp;  this list of conditions and the following disclaimer.<br />#&nbsp; &nbsp;  * Redistributions in binary form must reproduce the above copyright notice,<br />#&nbsp; &nbsp; &nbsp;  this list of conditions and the following disclaimer in the documentation<br />#&nbsp; &nbsp; &nbsp;  and/or other materials provided with the distribution.<br />#&nbsp; &nbsp;  * Neither the name of the CherryPy Team nor the names of its contributors<br />#&nbsp; &nbsp; &nbsp;  may be used to endorse or promote products derived from this software<br />#&nbsp; &nbsp; &nbsp;  without specific prior written permission.<br />#<br /># THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot; 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 />&nbsp; &nbsp; import thread<br />except ImportError:<br />&nbsp; &nbsp; import dummy_thread as thread<br /><br /># This import does nothing, but it&#039;s necessary to avoid some race conditions<br /># in the threading module. See http://code.djangoproject.com/ticket/2330 .<br />try:<br />&nbsp; &nbsp; import threading<br />except ImportError:<br />&nbsp; &nbsp; pass<br /><br /><br />RUN_RELOADER = True<br /><br />_mtimes = {}<br />_win = (sys.platform == &quot;win32&quot;)<br /><br />def code_changed():<br />&nbsp; &nbsp; global _mtimes, _win<br />&nbsp; &nbsp; for filename in filter(lambda v: v, map(lambda m: getattr(m, &quot;__file__&quot;, None), sys.modules.values())):<br />&nbsp; &nbsp; &nbsp; &nbsp; if filename.endswith(&quot;.pyc&quot;) or filename.endswith(&quot;.pyo&quot;):<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filename = filename[:-1]<br />&nbsp; &nbsp; &nbsp; &nbsp; if not os.path.exists(filename):<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue # File might be in an egg, so it can&#039;t be reloaded.<br />&nbsp; &nbsp; &nbsp; &nbsp; stat = os.stat(filename)<br />&nbsp; &nbsp; &nbsp; &nbsp; mtime = stat.st_mtime<br />&nbsp; &nbsp; &nbsp; &nbsp; if _win:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mtime -= stat.st_ctime<br />&nbsp; &nbsp; &nbsp; &nbsp; if filename not in _mtimes:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _mtimes[filename] = mtime<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue<br />&nbsp; &nbsp; &nbsp; &nbsp; if mtime != _mtimes[filename]:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _mtimes = {}<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return True<br />&nbsp; &nbsp; return False<br /><br />def reloader_thread(softexit=False):<br />&nbsp; &nbsp; &quot;&quot;&quot;If ``soft_exit`` is True, we use sys.exit(); otherwise ``os_exit``<br />&nbsp; &nbsp; will be used to end the process.<br />&nbsp; &nbsp; &quot;&quot;&quot;<br />&nbsp; &nbsp; while RUN_RELOADER:<br />&nbsp; &nbsp; &nbsp; &nbsp; if code_changed():<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # force reload<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if softexit:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.exit(3)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; os._exit(3)<br />&nbsp; &nbsp; &nbsp; &nbsp; time.sleep(1)<br /><br />def restart_with_reloader():<br />&nbsp; &nbsp; while True:<br />&nbsp; &nbsp; &nbsp; &nbsp; args = [sys.executable] + sys.argv<br />&nbsp; &nbsp; &nbsp; &nbsp; if sys.platform == &quot;win32&quot;:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; args = &#91;&#039;&quot;%s&quot;&#039; % arg for arg in args]<br />&nbsp; &nbsp; &nbsp; &nbsp; new_environ = os.environ.copy()<br />&nbsp; &nbsp; &nbsp; &nbsp; new_environ[&quot;RUN_MAIN&quot;] = &#039;true&#039;<br />&nbsp; &nbsp; &nbsp; &nbsp; exit_code = os.spawnve(os.P_WAIT, sys.executable, args, new_environ)<br />&nbsp; &nbsp; &nbsp; &nbsp; if exit_code != 3:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return exit_code<br /><br />def python_reloader(main_func, args, kwargs, check_in_thread=True):<br />&nbsp; &nbsp; &quot;&quot;&quot;<br />&nbsp; &nbsp; If ``check_in_thread`` is False, ``main_func`` will be run in a separate<br />&nbsp; &nbsp; thread, and the code checker in the main thread. This was the original<br />&nbsp; &nbsp; behavior of this module: I (Michael Elsdoerfer) changed the default<br />&nbsp; &nbsp; to be the reverse: Code checker in thread, main func in main thread.<br />&nbsp; &nbsp; This was necessary to make the thing work with Twisted<br />&nbsp; &nbsp; (http://twistedmatrix.com/trac/ticket/4072).<br />&nbsp; &nbsp; &quot;&quot;&quot;<br />&nbsp; &nbsp; if os.environ.get(&quot;RUN_MAIN&quot;) == &quot;true&quot;:<br />&nbsp; &nbsp; &nbsp; &nbsp; if check_in_thread:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thread.start_new_thread(reloader_thread, (), {&#039;softexit&#039;: False})<br />&nbsp; &nbsp; &nbsp; &nbsp; else:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thread.start_new_thread(main_func, args, kwargs)<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; try:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if not check_in_thread:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reloader_thread(softexit=True)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; main_func(*args, **kwargs)<br />&nbsp; &nbsp; &nbsp; &nbsp; except KeyboardInterrupt:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pass<br />&nbsp; &nbsp; else:<br />&nbsp; &nbsp; &nbsp; &nbsp; try:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.exit(restart_with_reloader())<br />&nbsp; &nbsp; &nbsp; &nbsp; except KeyboardInterrupt:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pass<br /><br />def jython_reloader(main_func, args, kwargs):<br />&nbsp; &nbsp; from _systemrestart import SystemRestart<br />&nbsp; &nbsp; thread.start_new_thread(main_func, args)<br />&nbsp; &nbsp; while True:<br />&nbsp; &nbsp; &nbsp; &nbsp; if code_changed():<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; raise SystemRestart<br />&nbsp; &nbsp; &nbsp; &nbsp; time.sleep(1)<br /><br /><br />def main(main_func, args=None, kwargs=None, **more_options):<br />&nbsp; &nbsp; if args is None:<br />&nbsp; &nbsp; &nbsp; &nbsp; args = ()<br />&nbsp; &nbsp; if kwargs is None:<br />&nbsp; &nbsp; &nbsp; &nbsp; kwargs = {}<br />&nbsp; &nbsp; if sys.platform.startswith(&#039;java&#039;):<br />&nbsp; &nbsp; &nbsp; &nbsp; reloader = jython_reloader<br />&nbsp; &nbsp; else:<br />&nbsp; &nbsp; &nbsp; &nbsp; reloader = python_reloader<br />&nbsp; &nbsp; 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__ == &quot;__main__&quot;:<br />&nbsp; &nbsp; .......<br />&nbsp; &nbsp; openerp.tools.autoreload_main(openerp.cli.main)<br />&nbsp; &nbsp; <br />
    

    1 条回复 最后回复
    0
    • C 离线
      C 离线
      ccdos
      写于 最后由 编辑
      #2

      强

      1 条回复 最后回复
      0
      • D 离线
        D 离线
        d_yang
        写于 最后由 编辑
        #3

        [quote author=ccdos link=topic=5992.msg15043#msg15043 date=1366354353]
        强
        [/quote]

        实在懒得Ctrl+C再回车了。

        1 条回复 最后回复
        0
        • W 离线
          W 离线
          wangbuke
          写于 最后由 编辑
          #4

          杨兄大作学习了 ~ 

          我这里也写了一个脚本,托管在 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")

          更多请移步本人博客 [检测到链接无效,已移除]

          欢迎指正!

          1 条回复 最后回复
          0
          • W 离线
            W 离线
            wangbuke
            写于 最后由 编辑
            #5

            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/

            1 条回复 最后回复
            0
            • D 离线
              D 离线
              d_yang
              写于 最后由 编辑
              #6

              强啊。
              经常拜读你的博客。

              1 条回复 最后回复
              0

              • 登录

              • 没有帐号? 注册

              • 登录或注册以进行搜索。
              • 第一个帖子
                最后一个帖子
              0
              • 版块
              • 标签
              • 热门
              • 用户
              • 群组