flask 源码阅读

flask是python下的一个web框架。类似的框架有很多,比如django,webpy等。本文介绍一下其中的一些源代码。

flask基于werkzeug,使用了werkzeug的很多工具。总的来说,flask(版本号0.10.1)主要文件如下:

flask/

__init__.py

app.py

blueprints.py

config.py

globals.py

json.py1.__init__.py

这个文件暴露flask的接口,从flask内部、werkzuug导入了很多工具。尤其值得一提的是,flask内部使用的json模块是作者从json|simplejson重载过来的。

2.app.py && blueprints.py

Flask类在此文件定义,这个类包含了很多常用的方法。比如route、和add_url_rule:

    def route(self, rule, **options):        """        :param rule: the URL rule as string        :param endpoint: the endpoint for the registered URL rule.  Flask                         itself assumes the name of the view function as                         endpoint        :param options: the options to be forwarded to the underlying                        :class:`~werkzeug.routing.Rule` object.  A change                        to Werkzeug is handling of method options.  methods                        is a list of methods this rule should be limited                        to (`GET`, `POST` etc.).  By default a rule                        just listens for `GET` (and implicitly `HEAD`).                        Starting with Flask 0.6, `OPTIONS` is implicitly                        added and handled by the standard request handling.        """        def decorator(f):            endpoint = options.pop('endpoint', None)            self.add_url_rule(rule, endpoint, f, **options)            return f        return decorator

? ? 这里用到了python下的修饰器,每次调用Flask.route("rule")时,Flask实例会将相关内容注册到Flask.url_mapFlask.view_functions里面,前者为werkzeug下的一个类Map的实例,包含url以及endpoint信息(均为字符串);后者为一个字典,根据endpoint索引对应的函数。blueprints.py里面包含类似的函数,不同的是在调用Flask.register_blueprint 时,处理函数才会被一次性注册到Flask实例里面。

? ? 除此之外,app.py 里面有一些比较特殊的函数,比如before_request, before_first_request,after_request等等,这些修饰符是用来给app注册在请求执行前后各自需要调用的函数的。

? ? 另外,Flask实例还提供了对http异常的处理,比如404,500页面如何返回等。这是通过修饰符Flask.errorhandler实现的。不得不说flask下修饰符的应用还是很普遍的。

3.globals.py

全部代码粘贴如下:

from functools import partialfrom werkzeug.local import LocalStack, LocalProxydef _lookup_req_object(name):    top = _request_ctx_stack.top    if top is None:        raise RuntimeError('working outside of request context')    return getattr(top, name)def _lookup_app_object(name):    top = _app_ctx_stack.top    if top is None:        raise RuntimeError('working outside of application context')    return getattr(top, name)def _find_app():    top = _app_ctx_stack.top    if top is None:        raise RuntimeError('working outside of application context')    return top.app# context locals_request_ctx_stack = LocalStack()_app_ctx_stack = LocalStack()current_app = LocalProxy(_find_app)request = LocalProxy(partial(_lookup_req_object, 'request'))session = LocalProxy(partial(_lookup_req_object, 'session'))g = LocalProxy(partial(_lookup_app_object, 'g'))

这是一份很神奇的代码,注释空格加起来不过30行左右,但是作用非常大。总的来说g, request,session 是线程共享(greenlets也算)的变量,可以在里面存放各种数据。在同样的上下文对这个获得这个变量并且对其进行的操作总是安全的。

关于flask是如何实现WSGI的,可以参看这篇文章:

flask的WSGI实现

?

?

?

?

?

?

?

?

?

flask 源码阅读

相关文章:

你感兴趣的文章:

标签云: