Flask源码剖析(1): 总览

Posted by xiezg247 on April 25, 2017

一. 背景

做一件事无非就三个过程,做这件事的目的是什么?有什么宗旨?想达到什么样的结果?

阅读一份源码应当也是同样的。

说到目的,要也得先知道这个目的从何而来。

有人说,人成熟的开始就是在不断认识自己的渺小和平凡,然后不断的妥协。

因此,为什么要剖析Flask源码?

目的大概是以下几点:

  • 如果这份代码在我的项目中使用了,那么它就是我的程序,必须对它负责,搞懂它。
  • 用户使用软件,他们并不在意是我的错误代码还是别人的引起的。所以,所有的bug都应当是我的bug。
  • 不要相信文档,文档永远都是过时的,只有不过时的代码,代码能给予最好的指引。

宗旨,这里指的是剖析源码采用的方法,参考知乎上面的回答,如何去阅读并学习一些优秀的开源框架的源码?/如何以“正确的姿势”阅读开源软件代码

我的建议只有三点:

  • 使用IDE看源码,一是直观,二是方便调试。
  • 几万行的项目随便折腾,找准一点研究就好啦,别管那么多方法论,怎么舒服怎么来。当然,掌握一定方法还是很有帮助的。
  • 抽象细节,纵览全局;抓住细节,深究原理。

那么所要达到预期的结果是:

  • 熟悉Flask组织结构,把握细节实现原理。
  • 更加深入理解python的基本实现方法。

二. 简介

Flask is a microframework for Python based on Werkzeug, Jinja 2 and good intentions.

“Micro” does not mean that your whole web application has to fit into a single Python file (although it certainly can), nor does it mean that Flask is lacking in functionality. The “micro” in microframework means Flask aims to keep the core simple but extensible. Flask won’t make many decisions for you, such as what database to use. Those decisions that it does make, such as what templating engine to use, are easy to change. Everything else is up to you, so that Flask can be everything you need and nothing you don’t.

By default, Flask does not include a database abstraction layer, form validation or anything else where different libraries already exist that can handle that. Instead, Flask supports extensions to add such functionality to your application as if it was implemented in Flask itself. Numerous extensions provide database integration, form validation, upload handling, various open authentication technologies, and more. Flask may be “micro”, but it’s ready for production use on a variety of needs.

以上来自Flask官网文档,从这段引用,我们可以得知几点:

  • Flask是一个微框架。
  • Flask是依赖WerkzeugJinja2开发的。
  • Flask是旨在保持核心简单,易于扩展。
  • 默认情况下,Flask不包含数据库抽象层、表单验证,或是其他任何多种库可以胜任的功能。
  • Flask支持扩展来给应用添加功能,其中包括数据库集成、表单验证、上传处理、各种各样的开放认证技术等。
  • Flask虽然看起来是微小的,但也可以在复杂的环境下使用。

三. 结构

这里研读的源码是Flask-0.12.tar.gz,结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
.
├── app.py                  # 主要提供创建flask实例和对请求、响应进行处理的功能
├── blueprints.py           # 提供模块化/蓝本功能
├── cli.py                  # 提供了命令行与flask app交互的功能
├── _compat.py              # 定义了对py2和py3的兼容,涉及到不同版本的对象,先在该文件中进行校验处理
├── config.py               # 主要提供配置文件的功能
├── ctx.py                  # 主要定义了上下文管理器的类
├── debughelpers.py         # 定义了各种debug模式的错误类型
├── ext                     # 提供flask.ext.扩展名的方式来导入“flask_扩展名”和“flaskext.扩展名”的功能
│   └── __init__.py
├── exthook.py              # 提供了ext目录需要用到的类,即导入钩子的类
├── globals.py              # 主要提供全局变量,局部变量和上下文管理器的实例
├── helpers.py              # 主要提供诸多辅助功能
├── __init__.py             # 提供了版本信息和需要导入的模块
├── json.py                 # 主要提供json格式数据的解析功能
├── logging.py              # 定义了日志管理器的类和创建函数
├── __main__.py             # 提供执行命令行交互的别名
├── sessions.py             # 提供session的类定义,包含了cookie机制
├── signals.py              # 主要提供不同机制的信号实例
├── templating.py           # 主要提供模板渲染功能
├── testing.py              # 定义用于测试而非生产的一些基类、函数等
├── views.py                # 提供另一种以类来定义视图函数的方式
└── wrappers.py             # 定义了对请求和响应的封装类

1 directory, 21 files

Tips: 初略浏览每个模块的注释,了解大概功能。

有效代码行数:

1
2
3
4
5
6
7
8
9
10
11
12
21 text files.
21 unique files.                              
0 files ignored.

http://cloc.sourceforge.net v 1.60  T=0.08 s (259.6 files/s, 80793.3 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Python                          21           1142           2653           2741
-------------------------------------------------------------------------------
SUM:                            21           1142           2653           2741
-------------------------------------------------------------------------------

app.py的有效代码行数:

1
2
3
4
5
6
7
8
9
10
1 text file.
1 unique file.                              
0 files ignored.

http://cloc.sourceforge.net v 1.60  T=0.01 s (67.2 files/s, 134301.5 lines/s)
-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Python                           1            318            998            684
-------------------------------------------------------------------------------

Flask的有效代码函数不过2k多,其中最主要的创建实例的文件app.py占据了1/4。

因此,我的建议是采用自顶而下的研读方法,理清楚源码的整体脉络,按照模块去阅读代码,记录类/函数之间的调用关系。

四. 组成

1. 标准库

String Services

Data Types

Numeric and Mathematical Modules

File and Directory Access

Data Compression and Archiving

Cryptographic Services

Generic Operating System Services

Optional Operating System Services

Internet Data Handling

Internet Protocols and Support

Python Runtime Services

Importing Modules

2. 第三方库