使用过Django和web.py,只是一直没有好好深入学习过,Django使用时间比较长,不过Django庞大了点,不适合我这种没耐心的人去学习,所以选择了web.py。
Hello World!
先看下web.py官方cookbook的“Hello World!”例子
import web
urls = ("/.*"), "hello")
app = web.application(urls, globals())
class hello:
def GET(self):
return 'Hello, world!'
if __name__ == "__main__":
app.run()
在例子中可以看到app.run()是启动了服务,而app的是application的一个实例,初始化工作是web.application(urls, globals()),就拿这个做入口,来看下application类的源码吧。
初始化
初始化的流程:
- 初始化mapping
- 把_load和_unload变成钩子加入到processors
- 把Reloader和reload_mapping变成钩子加入到processors
- 载入main所在模块
init的参数有三个,第一个mapping,上面例子中的urls;第二个fvars,例子中的globals(),globals()是python自带的一个函数,其返回值是全局名字空间,包括了函数、类、导入模块等等,是一个字典类型;第三个autoreload,是否允许自动重新载入。
mapping初始化
self.init_mapping(mapping)
def init_mapping(self, mapping):
self.mapping = list(utils.group(mapping, 2))
最后mapping的形式会是[[‘1’,‘2’],[‘1’,‘2’]]这样,这边就可以理解urls列表的样式了。
_load和_unload变成钩子加入到processors
关于钩子和处理器详见官网。
self.add_processor(loadhook(self._load))
self.add_processor(unloadhook(self._unload))
loadhook函数的作用就是在执行其参数传入的函数前执行一些操作,unloadhook则是在其后执行一些操作。这两个都类似于python的decorator。而_load和_unload则是将application实例本身加入web.ctx.app_stack或从其中移除。
如果autoreload不为True则初始化就到此为止了。在初始化的时候,如果autoreload为None,则回去参数读取web.config内的debug的值,默认为False,所以如果autoreload参数没有传入,一般都是不会自动加载,后面操作不会再去进行了。
Reloader和reload_mapping变成钩子加入到processors
和第二步相似,reload_mapping就是用来从新载入主的app,并初始化mapping。而Reloader则是在检查磁盘上任何模块是否有变化,如果有则重新加载。
重新import
通过main获取主app所在的模块名称和所在文件名,然后通过文件名重新import。这步还是简单的,不过代码值得一看,可以学好如sys.modules、getattr()及__import__()的用法。
启动服务
def run(self, *middleware):
return wsgi.runwsgi(self.wsgifunc(*middleware))
run函数调用wsgi模块的runwsgi函数,在hello world中就是启动一个http simple服务。具体内容等看到wsgi模块和httpserver模块再说了。