借用django.utils.autoreload实现python程序模块热插拔
Posted | archive
现代Web服务器应用一个重要的指标是“Uptime”,也就是在线时间。例如一个大型论坛,升级一个功能,如果需要更新配置而重启Web服务器,可能服务就暂停几秒种,几秒种的损失对于Web来说是相当大的,所以我们需要实现模块热插拔。升级一个模块之后,系统自动把内存里的代码更新为最新文件系统上的版本。再举一个例子,假如一个关键业务是一个IM聊天机器人,那么升级一个机器人的功能就不可能让机器人下线再上线。软件系统模块“热插拔”就像硬件的plug ‘n’ play 一样,方便了开发流程,把文件上传到服务器FTP,网站就自动更新。
实现思路很简单,犯不着去调用文件系统的消息和事件,我们用最原始最简单的办法:用一个单独的线程,隔一段时间遍历当前目录下的 .py 和 .pyc 文件,搜集文件时间属性,如果文件时间属性变化了,则 reload(module)
其实django内置的开发服务器已经实现了这个功能,你保存一个工程的代码,服务器在不重启的情况下自动刷新,那么秉着“不要重复造轮子”的理念,我们直接用django现有的模块。网上问了一下,发现是这个模块在起作用: django.utils.autoreload 。其实retoreload.py也是源自于CherryPy Project的一段代码。
调用就很简单了
#!/usr/bin/env python
#coding:utf-8
from django.utils import autoreload
def main():
print 1
#必须从命令行启动
if "__main__" == __name__:
import autoreload
autoreload.main(main)
保存为 test.py ,命令行运行 python test.py ,显示 1,说明代码没有问题。好,打开 test.py 修改main()函数为 print 2,保存,发现命令行自动刷新了,显示2。
如果上面的代码在工程中应用,可以在main()里写不能down的监护进程,然后所有功能通过 from module import class 来实现,要更新一个功能,只需要更新 module 文件,整个服务在不中断的情况下就会自动升级,我们就成功实现了模块热插拔。
脚本语言的确更加适合Web,如果是C语言开发的系统,每更新一个功能模块都需要编译一次,开发效率真是底下(当然用 .so/ .dll / COM 等技术就比较高级一点了)
Comments