在Python中无需重启主脚本加载/重载部分代码
简介
我最近在玩Twisted,刚学Python不到一个月。我最开始的想法是玩一些我熟悉的东西,比如IRC(互联网聊天)。多亏了ircLogBot.py这个例子,我已经成功建立了一个基本的IRC连接。
问题
我想要一些代码可以在每次收到IRC事件(比如私信、CTCP、加入或离开频道)时运行。为了方便调试,我希望能在不关闭整个脚本和重新连接IRC服务器的情况下,修改这段代码并重新加载它。
最后的说明
这个解决方案不一定要用Twisted,因为我对它还不是很了解。不过我猜,作为一个事件驱动的框架,Twisted应该能很好地处理这种情况。
4 个回答
你可以看看 'livecoding',这个工具可以处理代码的重新加载,可能会符合你的需求。不过要注意,'livecoding' 对代码文件(文件夹)有自己的要求,这些要求不一定符合 Python 的标准。
另外一个选择是自己动手做一个系统,使用 reload
,就像 Raymond 提到的那样。如果你的代码和状态数据分开得很好,可能会很容易实现。
Twisted里有一个内置的功能,叫做 twisted.python.rebuild
,它比Python自带的 reload
函数更强大。虽然它也有一些限制,但它最大的不同之处在于,它能找到旧的对象实例,并把它们的类替换成新版本的类。(主要的限制是,如果你修改了 __init__
方法,你需要注意你的实例可能会有旧的状态,这些状态和你当前的版本不匹配,这就是 rebuild.Sensitive
的作用。)
如果你想让事情变得更炫、更自动化,你可以设置一个文件系统监控器,来检测文件的变化,并在文件变化时用 rebuild 重新加载相关的模块。在Linux上,你可以使用Twisted的 inotify
来接收变化通知,而在OS X上,你可以使用 cfreactor
和 FSEvents
API,通过 PyObjC 来实现。(我不太清楚在win32上有哪些文件修改监控方案,但那里也可能有类似的功能。)
设置一个定期的事件(每隔几秒)来重新加载你正在调试的模块。可以使用内置的 reload() 函数来实现这个功能。
你可能想把它放在一个try/except块里,这样如果你在调试的模块中引入了错误,它也能处理这个情况。这样可以让服务器在出现错误时仍然保持运行 :-)