文章屬於做者原創,原文發佈在我的博客。html
Flask 官網上對它的定位是一個「微」 python web 開發框架。python
Flask is a micro web development framework for Python.linux
python 語言 web 框架不少:Django、Tornado、webpy、bottle……,flask 的特色是簡單可擴展。簡單有幾個方面,好比它只實現 web 框架最核心的功能,保持功能的簡潔;還有一個就是代碼量少,核心代碼 app.py
文件只有 2k+ 行。可擴展就是容許第三方插件來擴充功能,好比數據庫可使用 Flask-SQLAlchemy
,緩存可使用 Flask-Cache
等等。web
下面這段代碼是 flask 官方文檔給出的 hello world 版本的 flask 應用:數據庫
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!' if __name__ == '__main__': app.run()
要理解 flask 的源碼,必須有必定的 python 基礎(對 decorator、magic method、iterator、generator 概念比較熟悉),否則的話,會有些吃力。另一個必須理解的概念是 WSGI,簡單來講就是一套 web server 和 web 框架/web 應用之間的協議。能夠閱讀我以前寫的 python wsgi 簡介 和翻譯的 什麼是 web 框架 ,或者自行搜索相關資料,熟悉這部分的內容。json
NOTE:本系列文章分析的 flask 版本號是 0.12
,其餘版本可能會有出入。flask
flask 有兩個核心依賴庫:werkzeug
和 jinja
,而 werkzeug
又是二者中更核心的。緩存
werkzeug
負責核心的邏輯模塊,好比路由、請求和應答的封裝、WSGI 相關的函數等;jinja
負責模板的渲染,主要用來渲染返回給用戶的 html 文件內容。restful
模板(template)是和 web 框架相對獨立的內容,好比 jinja 不是隻能用在 web 應用中,而 web 應用也能夠不處理模板(好比返回 raw text 或者 json/xml 結構數據,而不是 html 頁面)。flask
直接使用 jinja2
而不是把這部分也作成可擴展的看起來有悖它的設計原則,我我的的理解是:flask 是個寫網頁的 web 框架,不像 flask-restful
能夠專門作 json/xml
數據接口,必須提供模板功能,否則用戶就沒法使用。而若是不綁定一個模板庫的話,有三種方法:本身寫一個模板引擎、封裝一個可擴展的模板層,用戶能夠本身選擇具體的模板引擎、或者讓用戶本身處理模板。可是這些方法要麼增長實現的複雜度,要麼增長了使用的複雜度。網絡
werkzeug
的定位並非一個 web 框架,而是 HTTP 和 WSGI 相關的工具集,能夠用來編寫 web 框架,也能夠直接使用它提供的一些幫助函數。
Werkzeug is an HTTP and WSGI utility library for Python.
werkzeug
提供了 python web WSGI 開發相關的功能:
路由處理:怎麼根據請求中的 url 找到它的處理函數
request 和 response 封裝:能夠更好地讀取 request 的數據,也容易生成響應
一個自帶的 WSGI server,能夠用來測試環境運行本身的應用
好比,咱們可使用 werkzeug
編寫一個簡單的 hello world 的 WSGI app:
from werkzeug.wrappers import Request, Response def application(environ, start_response): request = Request(environ) text = 'Hello %s!' % request.args.get('name', 'World') response = Response(text, mimetype='text/plain') return response(environ, start_response)
除了和 web WSGI 相關的功能,werkzeug 還實現了不少很是有用的數據結構和函數。好比用來處理一個 key 對應多個值的 MultiDict
,不支持修改的字典 ImmutableDict
,能夠緩存類屬性的 cache_property
等等。若是有機會,能夠寫篇文章講講 werkzeug
的源碼(好吧,我又挖坑了)。
官網上,對 Jinja
的 介紹已經很清晰,它就是一個 python 實現的模板引擎,功能很是豐富。
Jinja2 is a full featured template engine for Python. It has full unicode support, an optional integrated sandboxed execution environment, widely used and BSD licensed.
Jinja
功能比較豐富,支持 unicode 解析、自動 HTML escape 防止 XSS 攻擊、繼承、變量、過濾器、流程邏輯支持、python 代碼邏輯集成等等。具體的功能和使用請參考官網的文檔,這裏就不介紹了。
閱讀源代碼是件耗時而又沒有直接產出的事情,因此必需要事先明確目的,否則會白白浪費時間。對於我來講,通常須要閱讀源碼有幾個可能的緣由:
在學習語言的時候遇到瓶頸,想借鑑和學習優秀項目的風格、思路、經驗等。好比在剛學習一門語言的語法以後,會發現本身仍是不能很好地使用它。這個時候,我通常會找一個項目來練手,而後閱讀一些優秀項目的代碼來參考它們的實現
工做中須要常常用到某個項目。好比你從事 web 開發, 常用 flask/Django 框架,熟悉它們的源碼可讓你在使用的時候更能駕輕就熟和有的放矢,並且遇到問題以後也能更容易去定位
本身想深刻理解某個領域的知識。對某個領域很是感興趣,想理解它的內部實現原理,或者乾脆本身想造個輪子,那麼閱讀源碼是很好的途徑
知道了本身要閱讀代碼,那麼怎麼去讀代碼呢?
最重要的是不要畏懼!記得我剛開始工做的時候,總以爲那些項目都是很是優秀的人編寫的高質量代碼,本身望塵莫及,尚未深刻以前就認爲本身確定看不懂,更不用去修改代碼了。但其實,只要是人寫的代碼就會有 bug,也會有能夠改進的地方,要有好的心態:欣賞好的代碼設計,但也要學會識別很差的代碼
不要鉅細無遺!閱讀代碼最怕的是在細節中糾纏不清,不只拖慢進度也會大挫信心。全部的代碼大概都是樹形的結構,開始最重要的是理清樹幹的結構,知道這個樹大概有幾個部分,分別負責什麼功能,它們之間的大概關係是啥就夠了。萬萬不可取的是盯着某個小樹葉研究半天,或者被藤蔓遮住了視線
帶着問題去閱讀!這個建議不只適用於代碼,也適用於全部的閱讀。若是在閱讀以前有了明確的目的,好比想知道程序是怎麼啓動的、某個 bug 是何時引入的、某個功能是怎麼實現的…… 帶着這些問題,目的性強,理解也更快
簡化再簡化!若是代碼的量級比較大,要學會簡化問題,找到代碼的核心。有幾種方法:忽略細節,好比你知道某個文件夾是不一樣的驅動,那麼只要理解它們的接口和大體功能就行,把細節當作黑盒;運行最簡單的代碼,經過一個 hello world 或者 quickstart 提供的例子做爲入口和理解單位;找到以前的版本,有了版本控制和網絡,不少項目很容易找到歷史版本,好比理解 linux 的話不少書會推薦 0.X 的版本,它的核心都在,理解也更方便
左右開弓!理解一個很大項目無外乎兩種方法——從上到下和從下到上。對於比較複雜的項目,靈活使用這兩種方法,從上到下容易找到脈絡,但有時候由於多態或者運行時加載的緣由很難往下跟蹤;從下到上掌握東西更牢固,更有針對性,但會看不清項目的全貌,不容理解總體。兩種方法同時使用,直到它們出現交匯,作到融會貫通
但願說了這麼多,能對你們之後讀代碼和工做有點幫助。那麼,從下一篇文章,咱們就正式開始 flask 源碼之旅了!