跳转到主要内容

使用循环分支实现Plone的即时代码重载

项目描述

https://github.com/collective/sauna.reload/raw/gh-pages/saunasprint_logo.jpg

sauna.reload:让你今天完成Plone开发后,在桑拿浴中放松身心

简介

sauna.reload 是一个开发者工具,每次你保存文件时都会重新启动 Plone 并重新加载你更改的源代码。重启过程针对速度进行了优化,比正常启动过程快得多。

  • 编辑你的代码

  • 保存

  • 转到浏览器并点击 刷新➔你的最新更改已生效

它极大地简化了你的 Plone 开发工作流程,并恢复了 Python 的敏捷性。

它适用于任何代码。

sauna.reload 在 OSX 和 Linux 上与 Plone 4.0 和 4.1 一起工作。从理论上讲,它也适用于 Windows,但目前还没有人研究过。

用户评论

“我不想使用 sauna.reload,因为我可以在重启的同时织一排……”

“不再每次 Plone 重启 30 秒就抽 5 分钟的烟……好吧,等等,这种快乐会引发诗意,我要停下来。”

安装

以下是简要的安装说明。

先决条件

为了利用 sauna.reload

  • 你知道如何开发自己的 Plone 扩展程序,以及构建 out 文件夹结构的基础

  • 你知道 UNIX 命令行基础知识

  • 你知道如何运行 buildout

  • 你正在运行 Linux 或 OSX 操作系统

使用此产品不需要任何预热 sauna 的知识。

安装buildout配置

推荐的安装配置是使用 ZEO 服务器 + 1 个客户端进行开发。此方法适用于 Plone 4.1 及更高版本。你可以使用 sauna.reload 而不需要单独的 ZEO 数据库服务器,使用 instance 命令,但 在这种情况下,你将面临重启时数据库损坏的风险

以下是在您的开发环境中启用 sauna.reload 的推荐方法。然而,由于此产品仅用于开发,因此数据丢失不应成为大问题。

sauna.reload 添加到您的 buildout.cfg 文件中

buildout.cfg:

[buildout]
eggs +=
    sauna.reload

# This section is either client1 / instance depending
# on your buildout
[instance]
zope-conf-additional = %import sauna.reload

OSX注意事项

如果您在 OSX 上使用 vim(或 macvim),则必须禁用 vim 的写回存档,以便 WatchDog 能够看到您的修改(否则,vim 将在每次保存时实际上创建一个新文件,而 WatchDog 不会将修改报告给 sauna.reload)。

因此,将以下内容添加到您的 .vimrc 文件的末尾

set noswapfile
set nobackup
set nowritebackup

已报告与其他一些 OSX 编辑器存在类似问题。欢迎提供有关这些问题的技巧和修复方法。

Ubuntu / Debian / Linux注意事项

如果您正在处理大量文件(无论是硬限制还是软限制),您可能需要提高您的 ulimit

104000 是已知的良好值。

如果您的 ulimit 太低,您将收到非常误导性的 OSError: No space left on device

用法:以启用重载的方式启动Plone

要启动具有重新加载功能的 Plone,您需要为您的客户端 1 命令提供特殊环境变量 RELOAD_PATH

# Start database server
bin/zeoserver start

# Start Plone with reload enabled
RELOAD_PATH=src bin/client1 fg

或者,如果您想优化加载速度,可以直接指定您的一些开发产品

RELOAD_PATH=src/my.product:src/my.another.product bin/client1 fg

当重新加载处于活动状态时,您应该在 Zope 启动时在控制台看到类似以下内容

2011-08-10 13:28:59 INFO sauna.reload Starting file monitor on /Users/moo/code/x/plone4/src
2011-08-10 13:29:02 INFO sauna.reload We saved at least 29.8229699135 seconds from boot up time
2011-08-10 13:29:02 INFO sauna.reload Overview available at: http://127.0.0.1:8080/@@saunareload
2011-08-10 13:29:02 INFO sauna.reload Fork loop starting on process 14607
2011-08-10 13:29:02 INFO sauna.reload Booted up new new child in 0.104816913605 seconds. Pid 14608

… 当你在 src 文件夹中保存某个文件时

2011-08-10 13:29:41 INFO SignalHandler Caught signal SIGINT
2011-08-10 13:29:41 INFO Z2 Shutting down
2011-08-10 13:29:42 INFO SignalHandler Caught signal SIGCHLD
2011-08-10 13:29:42 INFO sauna.reload Booted up new new child in 0.123936891556 seconds. Pid 14609

CTRL+C 应正常终止 Zope。关闭时可能仍有一些小问题或错误消息。

只有通过 z3c.autoinclude 加载的 eggs 可以重新加载。请确保您没有为 eggs 使用 buildout.cfg zcml = 指令,否则 sauna.reload 将静默忽略更改。

手动重载

还有从 Zope2 根目录手动重新加载代码的视图

http://127.0.0.1:8080/@@saunareload

使用sauna.reload进行调试

使用常规的 import pdb; pdb.set_trace() 在与 sauna.reload 结合时将正常运行,并且将 ipdb 作为 pdb 的替换也能很好地工作。当在 pdb 或 ipdb 中发生重新加载时,调试器将被终止。为了避免由于意外终止调试器而导致终端回显丢失,您可以在您的 ~/.pdbrc 中添加以下内容:

import termios, sys
term_fd = sys.stdin.fileno()
term_echo = termios.tcgetattr(term_fd)
term_echo[3] = term_echo[3] | termios.ECHO
term_result = termios.tcsetattr(term_fd, termios.TCSADRAIN, term_echo)

由于 ipdb 扩展了 pdb,此配置文件也将用于恢复终端回显。

sauna.reload 也应与 PdbTextMateSupportPdbSublimeTextSupport 一起很好地工作。不幸的是,我们还没有看到它与 vimpdb 一起工作。

背景

sauna.reload 是尝试在不具有问题的前提下重新创建 plone.reload。例如,无法重新加载新的解析视图或部件代码。此项目始于 2011 年 Plone Sauna Sprint。因此,名称为 sauna.reload

sauna.reload 通过使用分叉循环来进行重新加载。因此,实际上它并没有重新加载代码,而是重启了 Zope2 的一部分。这就是为什么它可以重新加载 plone.reload 无法加载的内容。

它在 Zope2 启动时执行以下操作:

  1. 通过挂钩到 PEP 302 加载器并更改它们的 z3c.autoinclude 目标模块(并针对旧版本软件包进行 fiveconfigure/metaconfigure 的猴子补丁)来延迟加载您的开发包。

  2. 启动一个监视线程,该线程监视您开发 py 文件中的更改。

  3. zope.processlifetime.IProcessStarting 事件中停止加载 Zope2,进入一个无限循环;在此之前,尝试加载您开发包的所有非开发依赖项(由 z3c.autoinclude 解决)。

  4. 它分叉一个新的子进程并让它通过循环。

  5. 通过调用 z3c.autoinclude(以及针对旧版本软件包的 fiveconfigure/metaconfigure)来加载所有您的开发包。这很快!

  6. 现在,每当监视线程检测到开发文件中的更改时,它将向子进程发出信号以关闭它,而子进程将向父进程发出信号,以便在它即将关闭时分叉一个新的子进程。

  7. 在死亡之前,子进程将 Data.fs.index 保存下来,以帮助新的子进程看到 ZODB 中的更改(通过加载保存的索引)。

  8. 转到 4

内部,sauna.reload 使用 WatchDog Python 组件来监视文件系统更改事件。

另请参阅 Ruby 人在分叉技巧上的讨论

事件

sauna.reload 在重新加载期间会发出一些事件。

sauna.reload.events.INewChildForked

在新的进程被分叉后立即发出。还没有安装任何开发包。如果您想在代码加载之前做些事情,这很有用。请注意,您不能在标记为重新加载的包上监听此事件,因为它在触发时尚未安装。

sauna.reload.events.INewChildIsReady

当所有开发包已安装到新分叉的子进程时发出。对于通知等很有用。

限制

sauna.reload 仅支持 Plone >= 4.0 用于 FileStorage 和 Plone >= 4.1 用于 ZEO ClientStorage。

不处理依赖项

sauna.reload 存在一个重大缺陷。因为它依赖于延迟加载要监视和重新加载的包,因此,所有依赖于这些包的包也应该定义为需要重新加载(在 RELOAD_PATH 中)。并且 sauna.reload 不会自动解决这些依赖关系!

强制加载所有依赖项

另一个潜在的麻烦制造者是,sauna.reloadRELOAD_PATH 中的每个包执行隐式的 <includeDependencies package="." /> 操作(为了预加载这些包的依赖关系以加快重新加载速度)。

这可能会破坏一些包。

不与核心包一起工作

我们很抱歉 sauna.reload 可能不会适用于所有人。例如,重新加载核心 Plone 包可能会很棘手,甚至不可能,因为许多包都被 CMFPlone 的 configure.zcml 明确包含,而且根本不使用 z3c.autoinclude。您必须从 CMFPlone 中移除依赖关系才能进行开发以使其正常工作……

产品安装顺序被更改

此外,由于产品安装顺序已被上述操作更改,如果您的产品在安装或导入时执行了一些奇怪的操作,您可能会遇到一些问题。

请将任何其他问题报告到 GitHub 问题跟踪器

故障排除

GitHub 上报告所有问题。

我的代码没有正确重载

您将在终端中看到正在进行的重新加载过程,但您的代码仍然没有被加载。

您应该会看到以下来自您产品的 zcml 路径的警告

2011-08-13 09:38:12 ERROR sauna.reload.child Cannot reload
src/sauna.reload/sauna/reload/configure.zcml.

请确保您的代码通过 z3c.autoinclude 与 Plone 连接,并且在 buildout.cfg 中不使用显式的 zcml = directive

  • 如果需要,则对 eggs 进行自动包含支持的重装

  • 从 buildout.cfg 中删除您的 eggs 的 zcml = 行

  • 重新运行 buildout(请记住 bin/buildout -c development.cfg)

  • 使用 sauna.reload 启用重新启动 Plone

我想排除我的meta.zcml从重载

可以通过在自定义 site.zcml 中强制它们在 forkloop 之前加载来手动排除配置文件重新加载。请注意,当使用 site-zcml 选项时,zope2instance 忽略 zcmlzcml-additional 选项。

在您的 buildout.cfg 中定义一个自定义 site.zcml

[instance]
recipe = plone.recipe.zope2instance
...
site-zcml =
  <configure xmlns="http://namespaces.zope.org/zope"
             xmlns:meta="http://namespaces.zope.org/meta"
             xmlns:five="http://namespaces.zope.org/five">
    <include package="Products.Five" />
    <meta:redefinePermission from="zope2.Public" to="zope.Public" />
    <five:loadProducts file="meta.zcml"/>

    <!-- Add include for your package's meta.zcml here: -->
    <include package="my.product" file="meta.zcml" />

    <five:loadProducts />
    <five:loadProductsOverrides />
    <securityPolicy component="Products.Five.security.FiveSecurityPolicy" />
  </configure>

我想排除所有meta.zcml从重载

是的。查看上面的提示,并使用以下片段代替

[instance]
recipe = plone.recipe.zope2instance
...
site-zcml =
  <configure xmlns="http://namespaces.zope.org/zope"
             xmlns:meta="http://namespaces.zope.org/meta"
             xmlns:five="http://namespaces.zope.org/five">
    <include package="Products.Five" />
    <meta:redefinePermission from="zope2.Public" to="zope.Public" />
    <five:loadProducts file="meta.zcml"/>

    <!-- Add autoinclude-directive for deferred meta.zcml here: -->
    <includePlugins package="sauna.reload" file="meta.zcml" />

    <five:loadProducts />
    <five:loadProductsOverrides />
    <securityPolicy component="Products.Five.security.FiveSecurityPolicy" />
  </configure>

sauna.reload未激活 - 控制台没有打印任何内容

确保您的 buildout.cfg 包含 zope-conf-additional 行。

如果使用单独的 development.cfg,请确保您使用它运行 buildout

bin/buildout -c development.cfg

源代码

GitHub 上。

致谢

  • Esa-Matti Suuronen [esa-matti aet suuronen.org]

  • Asko Soukka [asko.soukka aet iki.fi]

  • Mikko Ohtamaa(想法,文档编写)

  • Vilmos Somogyi(标志)。该标志最初是 2011 年 Sauna Sprint 的标志,由 Vilmos Somogyi 设计。

  • Martijn Pieters 在 Sauna Sprint 2011 上教我们 PEP 302 -loader 技巧。

  • Yesudeep Mangalapilly 为创建 WatchDog 组件并使用它为 Sauna Sprint 团队提供支持

感谢 Sauna Sprint 2011 上所有快乐的黑客们!

为创建此包消耗了至少 300 公斤啤酒。还有几公斤木材、一把斧头、一台链锯和一艘船。

我们仍然需要测试人员和贡献者。您非常受欢迎!

变更日志

0.5.5 (2016-02-24)

  • 为 watchdog 引起的讨厌的 KeyError 添加另一个解决方案 [datakurre]

0.5.4 (2016-02-24)

  • 为 watchdog 引起的讨厌的 KeyError 添加解决方案 [datakurre]

0.5.3 (2014-10-19)

  • 修复了在Zope版本 >= 2.13.19时,在关闭时显式关闭存储的问题。这导致在重新加载时出现属性错误,因为_rpc_mgr为None。在关闭连接和缓存之前测试is_connected。[sunew]

0.5.2 (2014-10-18)

  • 将“无法重新加载”记录为警告而不是错误,以避免触发事后调试。[sunew]

0.5.1 (2013-02-20)

  • 修复了在导入sauna.reload时forked进程的IOError。[datakurre]

0.5.0 (2012-12-28)

  • 在platform.uname在栈中丢失之前预先填充它。所有使用platform.uname()值的调用都会因IOError(10)而失败。[esteele]

  • 修复了在Plone 4.1和Zope 2.13上Products命名空间蛋的重新加载。[miohtama]

  • 记录导致子进程死亡的原因。[miohtama]

0.4.3 (2012-04-25)

  • 更新README关于ZEO客户端支持的说明,限制为Plone >= 4.1。[miohtama]

0.4.2 (2012-04-24)

  • 修复了BlogStorage支持(从0.3.3的回归)。[datakurre]

0.4.0 (2012-04-22)

0.3.3 (2011-10-17)

  • 修复了初始化多个重新加载的Archetype产品的问题。

0.3.2 (2011-08-21)

  • 修复与PdbSublimeText/TextMateSupport更好地工作。

  • README更新(主要排除zcmls从重新加载)。

0.3.1 – 2011-08-19

  • 支持在Plone 4.1上初始化的产品(例如Archetypes)。

  • 许可协议为ZPL。

0.3.0 (2011-08-12)

  • 支持Plone 4.1

  • 重度编辑README [miohtama]

  • 如果产品安装失败,显示漂亮的错误日志消息,例如无法重新加载。

0.2.1 (2011-08-03)

  • 添加INewChildIsReady事件并移动INewChildForked事件

  • 删除过度使用的打印语句并使用日志记录

  • 现在可以从包根重新加载__init__.py

0.2.0 (2011-08-04)

  • 支持初始化的产品(例如Archetypes)。

  • 手动重新加载的浏览器视图

  • 发出INewChildForked事件

  • 许多错误修复

0.1.1 (2011-08-03)

  • 添加了缺少的蛋描述。

  • 添加了遗忘的本地化重新加载。

  • 在README中添加了命令前缀$。

0.1.0 (2011-08-03)

  • 第一个实验性版本。

项目详情


下载文件

为您的平台下载文件。如果您不确定要选择哪个,请了解更多关于安装包的信息。

源分布

sauna.reload-0.5.5.tar.gz (29.4 kB 查看散列)

支持者