bottle(python的一个小的服务器框架)的源码阅读(一)

本文介绍了Python的微型Web框架Bottle的源码阅读,重点探讨了`@app.route`装饰器、路由注册、插件安装及`run()`函数的工作流程。通过分析关键代码,揭示了Bottle如何处理HTTP请求,包括静态和动态路由的匹配,以及自定义插件的应用场景。
摘要由CSDN通过智能技术生成

bottle学习的不是很多,用bottle实现了一个链接mongodb的server。
索性bottle的源码也不是很多(4000行,主要的代码部分)。
所以我就去读了一下源码:

from bottle import Bottle, run
from bottle.ext.mongo import MongoPlugin

app = Bottle()
plugin = MongoPlugin(uri='127.0.0.1', db='collection', json_mongo=True)
app.install(plugin)

@app.route('/', method='GET')
def main(mongodb):
    return "hello, world"
# 正式启动服务器,在8080端口
run(app, host=SERVER_HOST , post=SERVER_PORT)

先简化一下,分析上面几行的过程

补丁的安装

bottle支持各种补丁,可以自己定制一个,然后安装进去就可以了。

app = Bottle()
plugin = MongoPlugin(uri='127.0.0.1', db='collection', json_mongo=True)
app.install(plugin)

主要是上面这几行。
我们重点看一下install方法里面的情况。
各种牛b的代码,主要是
self.plugins.append(plugin)
这一行,把补丁加入到Bottle这个类的补丁plugins集合中。
具体什么时候运行的等下面再讲。

@app.route

这是个明显的decorator
对应Bottle类里面的def route:方法:

def decorator(callback):
    if isinstance(callback, basestring): callback = load(callback)
    for rule in makelist(path) or yieldroutes(callback):
        for verb in makelist(method):
            verb = verb.upper()
            route = Route(self, rule, verb, callback, name=name,
                                  plugins=plugins, skiplist=skiplist, **config)
            self.add_route(route)
         return callback
    return decorator(callback)

其实里面的东西并不是很多
由于我们只是执行
@app.route(‘/’, method=’GET’)
所以,其实就是执行下面代码一次。

route = Route(self, rule, verb, callback, name=name,
      plugins=plugins, skiplist=skiplist, **config) 
self.add_route(route)

里面的verb就是‘GET’, rule就是‘/’, callback就是被修饰的main函数。创建好route之后就会被 调用 add_route(route)

def add_route(self, route):
    self.routes.append(route)
    self.router.add(route.rule, route.method, route, name=route.name)         

self.routes.append(route)这个没什么好说。
self.router.add东西有点多,当然因为我们就是一个静态的路径(非正则的路径),所以其实就是

 if is_static and not self.strict_order:
     self.static.setdefault(method, {})
     self.static[method][self.build(rule)] = (target, None)
    return

如果是非静态的话,会解析然后调用
def _compile(self, method)加入到
self.dyna_regexes[method]这个里面。

run!!!

各种组装好之后就开始run了。
run的话,额,大概就是指定个server(默认为里面的WSGIRefServer),然后把app放在上面run,然后app会被调用call方法
然后调用wsgi方法
wsgi中有这么一行
out = self._cast(self._handle(environ))
先调用_handle
_handle里面
route, args = self.router.match(environ)
return route.call(**args)
调用 match里面就会调用
静态为例(里面的路径和方法我们在@app.route方法中已经填写过了)

if method in self.static and path in self.static[method]:
    target, getargs = self.static[method][path]
    return target, getargs(path) if getargs else {}

动态的也类似,然后就是各种给参数,
然后route.call(**args)
运行一下。

这个call会调用_make_callback方法,此方法预先执行各个补丁的apply方法,比如我的那个MongoPlugin补丁,就会被执行,然后把预先为这个方法传入参数比如传入个mongodb的连接。
main(mongodb = concrete_mongodb)
通过@cached_property的封装,保证每个方法包装一次。

然后就可以愉快的调用call了得到结果了。

看不懂?直接上图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值