摘要:簡介官網上對它的定位是一個微開發框架。另外一個必須理解的概念是,簡單來說就是一套和框架應用之間的協議。功能比較豐富,支持解析自動防止攻擊繼承變量過濾器流程邏輯支持代碼邏輯集成等等。那么,從下一篇文章,我們就正式開始源碼之旅了
文章屬于作者原創,原文發布在個人博客。
flask 簡介Flask 官網上對它的定位是一個“微” python web 開發框架。
Flask is a micro web development framework for Python.
python 語言 web 框架很多:Django、Tornado、webpy、bottle……,flask 的特點是簡單可擴展。簡單有幾個方面,比如它只實現 web 框架最核心的功能,保持功能的簡潔;還有一個就是代碼量少,核心代碼 app.py 文件只有 2k+ 行。可擴展就是允許第三方插件來擴充功能,比如數據庫可以使用 Flask-SQLAlchemy,緩存可以使用 Flask-Cache 等等。
下面這段代碼是 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 框架 ,或者自行搜索相關資料,熟悉這部分的內容。
NOTE:本系列文章分析的 flask 版本號是 0.12,其他版本可能會有出入。
兩個依賴flask 有兩個核心依賴庫:werkzeug 和 jinja,而 werkzeug 又是兩者中更核心的。
werkzeug 負責核心的邏輯模塊,比如路由、請求和應答的封裝、WSGI 相關的函數等;jinja 負責模板的渲染,主要用來渲染返回給用戶的 html 文件內容。
模板(template)是和 web 框架相對獨立的內容,比如 jinja 不是只能用在 web 應用中,而 web 應用也可以不處理模板(比如返回 raw text 或者 json/xml 結構數據,而不是 html 頁面)。flask 直接使用 jinja2 而不是把這部分也做成可擴展的看起來有悖它的設計原則,我個人的理解是:flask 是個寫網頁的 web 框架,不像 flask-restful 可以專門做 json/xml 數據接口,必須提供模板功能,不然用戶就無法使用。而如果不綁定一個模板庫的話,有三種方法:自己寫一個模板引擎、封裝一個可擴展的模板層,用戶可以自己選擇具體的模板引擎、或者讓用戶自己處理模板。但是這些方法要么增加實現的復雜度,要么增加了使用的復雜度。
werkzeugwerkzeug 的定位并不是一個 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 的源碼(好吧,我又挖坑了)。
Jinja2官網上,對 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 源碼之旅了!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/38373.html
摘要:我們知道響應分為三個部分狀態欄版本狀態碼和說明頭部以冒號隔開的字符對,用于各種控制和協商服務端返回的數據。 這是 flask 源碼解析系列文章的其中一篇,本系列所有文章列表: flask 源碼解析:簡介 flask 源碼解析:應用啟動流程 flask 源碼解析:路由 flask 源碼解析:上下文 flask 源碼解析:請求 flask 源碼解析:響應 response 簡介 在 f...
摘要:可以看到,雖然是同樣的請求數據,在不同的階段和不同組件看來,是完全不同的形式。請求還有一個不那么明顯的特性它不能被應用修改,應用只能讀取請求的數據。 這是 flask 源碼解析系列文章的其中一篇,本系列所有文章列表: flask 源碼解析:簡介 flask 源碼解析:應用啟動流程 flask 源碼解析:路由 flask 源碼解析:上下文 flask 源碼解析:請求 flask 源碼解...
摘要:但是這些對象和全局變量不同的是它們必須是動態的,因為在多線程或者多協程的情況下,每個線程或者協程獲取的都是自己獨特的對象,不會互相干擾。中有兩種上下文和。就是實現了類似的效果多線程或者多協程情況下全局變量的隔離效果。 這是 flask 源碼解析系列文章的其中一篇,本系列所有文章列表: flask 源碼解析:簡介 flask 源碼解析:應用啟動流程 flask 源碼解析:路由 flas...
摘要:月份發布了第版,收到不少網友的良好建議,所以又抽空進行了完善,當然也拖了不少時間。本書主要介紹的基本使用,這也是我一開始在學習過程中經常用到的。第章實戰,介紹了如何開發一個簡單的應用。聲明本書由編寫,采用協議發布。 showImg(https://segmentfault.com/img/remote/1460000007484050?w=200&h=152); 書籍地址 head-f...
摘要:中有一個非常重要的概念每個應用都是一個可調用的對象。它規定了的接口,會調用,并傳給它兩個參數包含了請求的所有信息,是處理完之后需要調用的函數,參數是狀態碼響應頭部還有錯誤信息。一般來說,嵌套的最后一層是業務應用,中間就是。 文章屬于作者原創,原文發布在個人博客。 WSGI 所有的 python web 框架都要遵循 WSGI 協議,如果對 WSGI 不清楚,可以查看我之前的介紹文章。 ...
閱讀 2833·2021-11-25 09:43
閱讀 2476·2021-10-09 09:44
閱讀 2801·2021-09-22 15:49
閱讀 2567·2021-09-01 11:43
閱讀 2541·2019-08-30 14:16
閱讀 464·2019-08-29 17:24
閱讀 3020·2019-08-29 14:00
閱讀 1382·2019-08-29 13:05