使用循环分支实现Plone的即时代码重载
项目描述
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 也应与 PdbTextMateSupport 和 PdbSublimeTextSupport 一起很好地工作。不幸的是,我们还没有看到它与 vimpdb 一起工作。
背景
sauna.reload 是尝试在不具有问题的前提下重新创建 plone.reload。例如,无法重新加载新的解析视图或部件代码。此项目始于 2011 年 Plone Sauna Sprint。因此,名称为 sauna.reload。
sauna.reload 通过使用分叉循环来进行重新加载。因此,实际上它并没有重新加载代码,而是重启了 Zope2 的一部分。这就是为什么它可以重新加载 plone.reload 无法加载的内容。
它在 Zope2 启动时执行以下操作:
通过挂钩到 PEP 302 加载器并更改它们的 z3c.autoinclude 目标模块(并针对旧版本软件包进行 fiveconfigure/metaconfigure 的猴子补丁)来延迟加载您的开发包。
启动一个监视线程,该线程监视您开发 py 文件中的更改。
在 zope.processlifetime.IProcessStarting 事件中停止加载 Zope2,进入一个无限循环;在此之前,尝试加载您开发包的所有非开发依赖项(由 z3c.autoinclude 解决)。
它分叉一个新的子进程并让它通过循环。
通过调用 z3c.autoinclude(以及针对旧版本软件包的 fiveconfigure/metaconfigure)来加载所有您的开发包。这很快!
现在,每当监视线程检测到开发文件中的更改时,它将向子进程发出信号以关闭它,而子进程将向父进程发出信号,以便在它即将关闭时分叉一个新的子进程。
在死亡之前,子进程将 Data.fs.index 保存下来,以帮助新的子进程看到 ZODB 中的更改(通过加载保存的索引)。
转到 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.reload 对 RELOAD_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 忽略 zcml 和 zcml-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)
添加了有关成功重新加载配置文件的日志信息。关闭https://github.com/epeli/sauna.reload/issues/11 [datakurre]
添加了对Plone >= 4.1上ZEO客户端重新加载的支持。修复https://github.com/collective/sauna.reload/issues/1 [datakurre]
当安装p.a.theming时添加了对p.a.themingplugins的支持。修复https://github.com/epeli/sauna.reload/issues/15 [datakurre]
修复了在重新加载期间配置产品时,zope2.Public未映射到zope.Public的问题。修复https://github.com/collective/sauna.reload/issues/2 [datakurre]
修复为依赖于watchdog >= 0.6.0以支持OSX out-of-the-box。[datakurre]
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的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 043f6e2658a09ba937ba432d48c5644d36177fe7b241f6a1eac92c87c4c95ecb |
|
MD5 | 75af3018ca9482382a735fdce2793b2f |
|
BLAKE2b-256 | a34ac8c1d25678dc650237704b21a10f8ae5bb72ee43080f65a154b4f555ece6 |