Falcon Tutorial(英文鏈接)
標(biāo)簽: 'REST' 'Falcon' 'Python'
1. 整體架構(gòu)(The Big Picture)
![架構(gòu)圖](http://falcon.readthedocs.org/en/stable/_images/my-web-app.gif)
2. 開始(First Steps)
在開始之前婉弹,先得保證falcon已經(jīng)安裝昌粤。然后創(chuàng)建一個(gè)新的project目錄“l(fā)ook”面殖,然后切換到該目錄:
$ mkdir look
$ cd look
然后冲茸,創(chuàng)建一個(gè)新文件app.py作為應(yīng)用入口:
$touch app.py
打開app.py,加入下面的內(nèi)容:
import falcon
api = application = falcon.API()
這樣就創(chuàng)建了一個(gè)WSGI應(yīng)用章母,并且設(shè)置別名為api
。我們可以使用任何變量名,Gunicorn希望我們默認(rèn)使用application
嗡官。
WSGI應(yīng)用只是一個(gè)可調(diào)用的明確定義的簽名,你可以在任何支持WSGI協(xié)議的web server上托管你的應(yīng)用毯焕。下面我們來看falcon.API類衍腥。
首先安裝IPython,并且啟動(dòng)它:
$ pip install ipython
$ ipython
然后纳猫,輸入下面的命令來查看falcon.API的調(diào)用
In [1]: import falcon
In [2]: falcon.API.__call__婆咸?
或者,你可以使用內(nèi)建的help
函數(shù)去查看:
In [3]: help(falcon.API.__call__)
注意method簽名芜辕。env
和start_response
是標(biāo)準(zhǔn)WSGI參數(shù)尚骄。Falcon在這些參數(shù)上層添加了少許抽象,所以我們不必直接去操作它們侵续。
Falcon框架包含大量的內(nèi)聯(lián)文檔倔丈,你可以通過使用上面介紹的技巧來查詢。經(jīng)過Falcon團(tuán)隊(duì)對文檔可讀性的大量優(yōu)化状蜗,我們可以很快瀏覽和查找我們需要的需五。
Tip
bpython是另一個(gè)非常給力的REPL(交互式解釋器),可以加入我們的工具箱轧坎,以便以后瀏覽新的library(庫)宏邮。
3. 托管應(yīng)用(Hosting Your App)
現(xiàn)在我們已經(jīng)創(chuàng)建了一個(gè)簡單的Falcon應(yīng)用,我們可以讓它運(yùn)行在WSGI server上缸血。Python包含一個(gè)自托管的參考server蜜氨,但是我們還是使用實(shí)際部署時(shí)使用的server。
$ pip install gunicorn
$ gunicorn app
現(xiàn)在我們使用curl嘗試查詢它:
$ curl localhost:8000 -v
你將會(huì)獲取到404属百。這很正常记劝,因?yàn)槲覀儧]有設(shè)定任何路由(route)。Falcon包含默認(rèn)的404響應(yīng)處理(response handler)族扰,用來處理沒有匹配到任何路由的請求地址厌丑。
使用curl可能會(huì)有點(diǎn)蛋疼,我們可以安裝HTTPie渔呵,從今以后就使用它了怒竿。
$ pip install --upgrade httpie
$ http localhoost:8000
4. 創(chuàng)建資源(Creating Resources)
Falcon從REST架構(gòu)風(fēng)格
引入了一些術(shù)語,如果你熟悉REST概念扩氢,那么對Falcon應(yīng)該會(huì)比較熟悉耕驰。不過,就算完全不懂REST
录豺,也不用擔(dān)心朦肘。Falcon的設(shè)計(jì)理念是饭弓,盡可能直觀地讓所有人理解HTTP基本原理。
在Falcon中媒抠,我們可以把傳入的請求(incoming requests)稱為資源
(Resources)弟断。資源
只是一個(gè)常規(guī)class,包含一些遵循一定命名規(guī)則的方法(method)趴生。每個(gè)方法對應(yīng)一個(gè)動(dòng)作(API客戶端為了獲取或轉(zhuǎn)換資源阀趴,去請求執(zhí)行的動(dòng)作)。
假設(shè)我們在構(gòu)建一個(gè)圖片分享API苍匆,那我們可以創(chuàng)建一個(gè)image
資源刘急。在我們的項(xiàng)目目錄中,創(chuàng)建一個(gè)image.py
的文件浸踩,可以在里面添加下面的代碼:
import falcon
class Resource(object):
def on_get(self, req, resp):
resp.body = '{"message":"Hello woeld!"}'
resp.status = falcon.HTTP_200
可見,Resource
只是一個(gè)很常規(guī)的class叔汁,類名可以任意取。Falcon使用duck-typing
民轴,所以不需要繼承任何特定的基類攻柠。
上面的image資源定義了單一方法on_get
。對于resource想要支持的任何HTTP方法后裸,只需要簡單在resource上加on_x
類方法(class method)瑰钮,x
可以是標(biāo)準(zhǔn)HTTP方法中的任何一個(gè),例如on_get
,on_put
,on_head
(小寫)等等微驶。
我們將這些著名的方法稱作responders
(響應(yīng)器)浪谴。每個(gè)responder
至少需要兩個(gè)參數(shù),一個(gè)代表HTTP請求因苹,另一個(gè)代表對應(yīng)請求的HTTP響應(yīng)苟耻。根據(jù)習(xí)慣,我們一般寫作req
和resp
扶檐。route(路由)模板和hooks(鉤子)可以添加一些額外的參數(shù)凶杖,在后面將會(huì)講到。
現(xiàn)在款筑,image資源對GET請求作出響應(yīng):200 ok
和一個(gè)JSON
對象智蝠。Falcon默認(rèn)是application/json
作為互聯(lián)網(wǎng)媒體類型,但是你可以設(shè)置成任何你想使用的類型奈梳。例如杈湾,你可以使用MessagePack或者其他序列化格式。
如果你想在上面的例子中使用MessagePack
攘须,你需要為Python安裝序列化/反序列化漆撞。通過運(yùn)行pip install msgpack-python
,然后更新你的responder中相應(yīng)的響應(yīng)數(shù)據(jù)(response data)和內(nèi)容類型(content_type):
import falcon
import msgpack
class Resource(object):
def on_get(self, req, resp):
resp.data = msgpack.packb({'message':'Hello world!'})
resp.content_type = 'application/msgpack'
resp.status = falcon.HTTP_200
注意,使用resp.data
代替resp.body
浮驳。如果你給后者resp.body
指定一個(gè)bytestring悍汛,F(xiàn)alcon也能處理,但是通過直接指定resp.data
你將獲得一些性能提升至会。
現(xiàn)在關(guān)聯(lián)上resource员凝,看其運(yùn)行得如何》芟祝回到app.py
,并且將其修改成下面的形式:
import falcon
import images
api = application = falcon.API()
images = images.Resource()
api.add_route('/images', images)
現(xiàn)在旺上,如果傳入一個(gè)“/images”的請求瓶蚂,F(xiàn)alcon請會(huì)調(diào)用images的資源中的響應(yīng)器(responder)--對應(yīng)所需要的HTTP方法。
重啟gunicorn宣吱,并且嘗試向resource(資源)發(fā)送一個(gè)GET請求:
$ http GET localhost:8000/images
Tip
duck-typing
:動(dòng)態(tài)類型的一種風(fēng)格窃这。在這種風(fēng)格中,一個(gè)對象有效的語義征候,不是由繼承自特定的類或?qū)崿F(xiàn)特定的接口杭攻,而是由當(dāng)前方法和屬性的集合決定。在duck typing中疤坝,關(guān)注的不是對象的類型本身兆解,而是它是如何使用的。
5. 請求對象和響應(yīng)對象(Request and Response Objects)
資源(resource)中的每個(gè)響應(yīng)器(responder)接收一個(gè)請求對象(request oject)--可以被用作讀取headers跑揉、查詢參數(shù)和請求的body锅睛。你可以使用我們之前提到的help
函數(shù)去列舉Request類的成員:
In [1]: import falcon
In [2]: help(falcon.Request)
每個(gè)響應(yīng)器(responder)也能接收一個(gè)響應(yīng)對象(response object)--可以被用作設(shè)置HTTP狀態(tài)碼、headers和響應(yīng)的body历谍。你可以通過使用同樣的技巧來列舉Response的類成員:
In [3]: help(falcon.Response)
讓我們探究一下他們?nèi)绾芜\(yùn)作现拒。當(dāng)客戶端(client)POST到images集合(collection)時(shí),我們要?jiǎng)?chuàng)建一個(gè)新的image資源望侈。首先印蔬,我們需要指定images保存在什么地方(對于真實(shí)的service,你將需要使用一個(gè)對象儲(chǔ)存服務(wù)脱衙,例如Cloud Files 或者Amazon S3)侥猬。
編輯你的images.py
文件,添加下列代碼到resource:
def __init__(self, storage_path)
self.storage_path = storage_path
然后岂丘,編輯app.py
陵究,然后傳入一個(gè)path參數(shù)到resource的初始化器。
最后奥帘,實(shí)現(xiàn)POST響應(yīng)器(responder):
import os
import time
import uuid
import falcon
def _media_type_to_ext(media_type):
#剝離'/images/'前綴
return media_type[6:]
def _generate_id():
return str(uuid.uuid4())
class Resource(object):
def __init__(self, storage_path):
self.storage_path = storage_path
def on_post(self, req, resp):
image_id = _generate_id()
ext = _media_type_to_ext(req.content_type)
filename = image_id + '.' + ext
image_path = os.path.join(self.storage_path, filename)
with open(image_path, 'wb') as image_file:
while True:
chunk = req.stream.read(4096)
if not chunk:
break
image_file.write(chunk)
resp.status = falcon.HTTP_201
resp.location = '/images/' + image_id
正如我們所看見的铜邮,我們給新圖片生成了一個(gè)唯一的ID和文件名,然后從req.stream
讀取出來,再寫入文件松蒜。調(diào)用stream
而不是body
去強(qiáng)調(diào)事實(shí)--你確實(shí)正在從輸入流讀取;Falcon不會(huì)輸出(spool)或解碼(decode)請求數(shù)據(jù)(request data)扔茅,而是讓你直接訪問由WSGI server提供的二進(jìn)制輸入流(incoming binary stream)。
注意秸苗,我們將HTTP response status code
設(shè)置為“201 Created”召娜。預(yù)定義的狀態(tài)字符清單,我們可以通過對falcon.status_codes
調(diào)用help
函數(shù)來查看:
In [4]: help(falcon.status_codes)
在on_post
響應(yīng)器的最后一行惊楼,給新創(chuàng)建的資源設(shè)置Location Header玖瘸。(我們很快就給該路徑(path)創(chuàng)建一個(gè)了路由(route))注意,Request類和Response類包含一些讀取和設(shè)置通用header的便利屬性檀咙,但是通過聲明req.get_header
和resp.set_header
方法雅倒,我們總是可以使用任何header.
重啟gunicorn,然后嘗試給resource發(fā)送一個(gè)POST請求(可以將test.jpg替換成任何你想操作的JPEG文件的路徑)
$ http POST localhost:8000/images Content-type:image/jpeg < test.jpg
如果現(xiàn)在去查看你儲(chǔ)存目錄弧可,將會(huì)包含你剛才POST的圖片的復(fù)制品蔑匣。
6. 提供圖片(Serving Images)##
我們現(xiàn)在已經(jīng)可以上傳圖片到服務(wù)了,我們還要能獲取他們棕诵。我們要做的就是裁良,通過帶有路徑的請求,讓服務(wù)器返回一張圖片到Location header校套,就像這樣:
$ http GET localhost:8000/images/87db45ff42
接下來价脾,我們可以在images資源中添加on_get
響應(yīng)器,這樣做對于比較簡單的resource是可行的笛匙,但是這種方法會(huì)導(dǎo)致一個(gè)問題--當(dāng)同一個(gè)HTTP方法(例如GET)需要作出不同的響應(yīng)彼棍。所以具體取決于使用者想要處理一系列的事件還是單個(gè)事件。
按照這個(gè)思路膳算,如果我們要處理多張圖片座硕,除了表示單張圖片資源的類以外,還需要新建一個(gè)類涕蜂。我們可以在新的類中添加on_get
響應(yīng)器华匾。
我們按照下面這樣,繼續(xù)編輯images.py
:
import os
import time
import uuid
import falcon
def _media_type_to_ext(media_type):
# 剝離'/images/'前綴
return media_type[6:]
def _ext_to_media_type(ext):
return 'image/' + ext
def _generate_id():
return str(uuid.uuid4())
class Collection(object):
def __init__(self, storage_path):
self.storage_path = storage_path
def on_post(self, req, resp):
image_id = _generate_id()
ext = _media_type_to_ext(req.content_type)
filename = image_id + '.' + ext
image_path = os.path.join(self.storage_path, filename)
with open(image_path, 'wb') as image_file:
while True:
chunk = req.stream.read(4096)
if not chunk:
break
image_file.write(chunk)
resp.status = falcon.HTTP_201
resp.location = '/images/' + filename
class Item(object):
def __init__(self, storage_path):
self.storage_path = storage_path
def on_get(self, req, resp, name):
ext = os.path.splitext(name)[1][1:]
resp.content_type = _ext_to_media_type(ext)
image_path = os.path.join(self.storage_path, name)
resp.stream = open(image_path, 'rb')
resp.stream_len = os.path.getsize(image_path)
可以看到机隙,剛才我們將Resource
重命名為Collection
蜘拉,并且添加了一個(gè)Item
類去表示單張圖片資源。還有有鹿,我們需要注意到on_get
響應(yīng)器中的name
參數(shù)旭旭。任何在路由中指定的URL參數(shù)都將被轉(zhuǎn)換成對應(yīng)的kwargs參數(shù),同時(shí)傳遞到目標(biāo)響應(yīng)器(responder)中葱跋。之后持寄,將會(huì)講解如何指定URL參數(shù)源梭。
在on_get
響應(yīng)器中,我們按照文件名擴(kuò)展去設(shè)置內(nèi)容類型的header稍味,然后通過打開文件操作來直接以數(shù)據(jù)流形式輸出圖片废麻。還有需要注意resp.stream_len
的用法。每當(dāng)我們使用resp.stream
來代替resp.body
或resp.data
的時(shí)候模庐,我們必須給數(shù)據(jù)流指定一個(gè)預(yù)期的長度烛愧,以便web客戶端知道從響應(yīng)(response)中讀取的數(shù)據(jù)有多大。
Tips
如果你事先不知道數(shù)據(jù)流的大小掂碱,你可以通過使用分塊編碼怜姿,這個(gè)用法超過該教程范圍。
如果resp.status
沒有明確地設(shè)定疼燥,其默認(rèn)值為200 OK
社牲,確切的說,這應(yīng)該是我們應(yīng)該在on_get
響應(yīng)器去做的悴了。
現(xiàn)在我們將事件關(guān)聯(lián)上,然后嘗試運(yùn)行一下违寿。首先按照下面的例子來編輯app.py
:
import falcon
import images
api = application = falcon.API()
storage_path = '/usr/local/var/look'
image_collection = images.Collection(storage_path)
image = image.Item(storage_path)
api.add_route('/images', image_collection)
api.add_route('/images/(name)', image)
可見湃交,我們定義了一個(gè)新的路由/images/{name}
。這會(huì)讓Falcon將所有的對應(yīng)的響應(yīng)器(responder)和獲取的name
參數(shù)關(guān)聯(lián)起來藤巢。
Tips
Falcon還支持更加復(fù)雜的參數(shù)化路徑段(包含多個(gè)值)搞莺。例如,類Grasshopper(GH-like,可以通過參數(shù)的調(diào)整直接改變模型形態(tài))的API能夠使用下面的模板為兩個(gè)分支添加一個(gè)路由掂咒。
/repo/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}
然后才沧,我們重啟gunicorn,并且post并一張圖片給service:
$ http POST localhost:8000/images Content-type:image/jpeg < test.jpg
記下在Location header中返回的路徑绍刮,然后使用該路徑去GET這張圖片:
$ http localhost:8000/images/6daa465b7b.jpeg
HTTPie默認(rèn)不會(huì)下載圖片温圆,但是我們可以看到響應(yīng)(response)的header被設(shè)置好了。更有趣的是孩革,我們可以繼續(xù)在瀏覽器中輸入剛才的URL岁歉,圖片會(huì)被正確的顯示出來。
7. “鉤子”簡介(Introducing Hooks)
看到這里膝蜈,我們應(yīng)該對Falcon基礎(chǔ)API有了較好的理解锅移。在教程結(jié)束前,我們需要花費(fèi)一點(diǎn)時(shí)間去整理代碼饱搏,并且加上一些錯(cuò)誤處理非剃。
第一步,當(dāng)接收到一個(gè)POST請求時(shí)推沸,檢查輸入的媒體類型(incoming media type)去確認(rèn)是否為通用圖像類型备绽。我們可以通過使用Falcon的before
鉤子來完成券坞。
@wjy 2015-12-22 18:26 字?jǐn)?shù) 8599 閱讀 22
首先,我們需要定義一個(gè)service接收的媒體類型列表疯坤。將這些常量定義放在代碼頂部报慕,也就是images.py
文件的import聲明后面。
ALLOWED_IMAGE_TYPES = (
'image/gif',
'image/jpeg',
'image/png',
)
這樣聲明只接收GIF压怠、JPEG眠冈、PNG圖像格式,當(dāng)然你也可以添加你想要的其它格式菌瘫。
接下來蜗顽,在每個(gè)請求post消息前創(chuàng)建一個(gè)鉤子。并且在ALLOWED_IMAGE_TYPES
下面添加該方法:
def validate_image_type(req, resp, params):
if req.content_type not in ALLOWED_IMAGE_TYPES:
msg = 'Image type not allowed. Must be PNG, JPEG, or GIF'
raise falcon.HTTPBadRequest('Bad request', msg)
然后將這個(gè)鉤子附加在on_post
響應(yīng)器上雨让,如下:
@falcon.before(validate_image_type)
def on_post(self, req, resp):
這樣雇盖,每當(dāng)這個(gè)on_post
響應(yīng)器被調(diào)用前,F(xiàn)alcon將先執(zhí)行(invoke)validate_image_type
這個(gè)方法栖忠。除了必須接受三個(gè)參數(shù)外崔挖,該方法并沒有什么特別的。對于每個(gè)鉤子庵寞,會(huì)引用傳遞進(jìn)對應(yīng)響應(yīng)器(responder)的req
和reqsp
對象狸相,作為前2個(gè)參數(shù)。第三個(gè)參數(shù),習(xí)慣上被稱作params
,引用自Falcon為每個(gè)request創(chuàng)建的kwarg字典廊谓。如果params
存在的話,將包含路由的URL模板參數(shù)及其對應(yīng)的值瘸右。
由此可見,我們可以使用req
去獲得關(guān)于傳入的請求的相關(guān)信息岩齿。而且需要的話太颤,我們也可以使用resp
去操作HTTP響應(yīng),為了避免重復(fù)代碼(in a DRY way)我們甚至可以給響應(yīng)器(responder)添加額外的kwarg盹沈,例如:
def extract_project_id(req, resp, params):
"""
為所有響應(yīng)器的params添加'project_id'栋齿。
意味著將在'before'鉤子中被使用
"""
params['project_id'] = req.get_header('X-PROJECT-ID')
現(xiàn)在我們可以想象,這樣的一個(gè)鉤子應(yīng)該適用于一個(gè)資源(resource)的所有響應(yīng)器(responder)襟诸,甚至可以適用于全局范圍內(nèi)的所有資源瓦堵。我們還可以將鉤子應(yīng)用到整個(gè)資源上,如下:
@falcon.before(extract_project_id)
class Message(object):
#...
而且歌亲,在API類初始化時(shí)將鉤子作為參數(shù)傳遞進(jìn)去菇用,我們可以全局應(yīng)用:
falcon.API(before=[extract_project_id])
如果想對鉤子(hooks)進(jìn)一步了解,可以查閱API
類的幫助文檔陷揪,也有裝飾器falcon.before
和falcon.after
的幫助文檔惋鸥。
至此杂穷,我們已經(jīng)添加了一個(gè)鉤子--在圖像被POST時(shí)確認(rèn)媒體類型。你可以實(shí)際操作一下卦绣,比如傳入一些邪惡的東西耐量,看看發(fā)生什么:
$ http POST localhost:8000/images Content-Type:image/jpx < test.jpx
不出意外,會(huì)返回400 Bad Request
狀態(tài)和結(jié)構(gòu)分明的錯(cuò)誤body滤港。當(dāng)出現(xiàn)錯(cuò)誤時(shí)廊蜒,我們通常想給用戶一些信息,來幫助他們解決問題溅漾。這個(gè)規(guī)則有個(gè)例外山叮,用戶請求訪問未授權(quán)的東西時(shí)產(chǎn)生的錯(cuò)誤。這種情況添履,我們應(yīng)該希望去僅僅返回一個(gè)404 Not Found
的空body屁倔,防止惡意用戶想要獲得一些能幫助他們破解我們API的信息。
Tip
可以關(guān)注一下我們的姊妹項(xiàng)目--Talcons暮胧,由社區(qū)貢獻(xiàn)的一些游泳的Falcon鉤子锐借。如果你創(chuàng)建了一些有趣的鉤子,同時(shí)你認(rèn)為別人也需要往衷,可以考慮貢獻(xiàn)到該項(xiàng)目钞翔。
8. 錯(cuò)誤處理(Error Handling)
通常來講,F(xiàn)alcon假定資源的響應(yīng)器(on_get,on_post等)在大部分情況下能正確運(yùn)作炼绘。也就是說,F(xiàn)alcon在保護(hù)響應(yīng)器代碼上沒有做太多工作妄田。
(通常)這樣可以減少多余的檢查俺亮,F(xiàn)alcon可以專注運(yùn)行一些核心代碼,使得框架更高效疟呐。在這種理念下脚曾,利用Falcon構(gòu)建一個(gè)高質(zhì)量的API需要:
1.資源響應(yīng)器將響應(yīng)變量設(shè)置為完整值
2.大部分代碼易于測試
3.錯(cuò)誤應(yīng)該是可預(yù)見、易查明启具,并且能在每個(gè)響應(yīng)器中做作相應(yīng)處理本讥。
Tip
除非已經(jīng)注冊自定義處理這種情況的程序,不要繼承falcon.HTTPError
,否則Falcon將會(huì)重新拋出錯(cuò)誤鲁冯。(詳情請見:falcon.API)
談到錯(cuò)誤處理拷沸,當(dāng)發(fā)生一些可怕的(輕度的)錯(cuò)誤,我們可以手動(dòng)設(shè)置錯(cuò)誤狀態(tài)薯演、合適的響應(yīng)header撞芍、甚至是一個(gè)使用resp
對象的錯(cuò)誤body。然而跨扮,F(xiàn)alcon通過提供一套在錯(cuò)誤發(fā)生時(shí)可能拋出的異常序无,使得處理更加容易验毡。事實(shí)上,如果Falcon捕獲到(catch)繼承自falcon.HTTPError
的響應(yīng)器(responder)拋出的任何異常帝嗡,框架會(huì)將異常轉(zhuǎn)換成對應(yīng)的HTTP錯(cuò)誤響應(yīng)晶通。
你可以拋出falcon.HTTPError
的實(shí)例,或者使用一些預(yù)定義的錯(cuò)誤類--嘗試做一些正確的事情去設(shè)置header和body哟玷。查閱下面的文檔狮辽,你可以獲得橫多關(guān)于在你的API中如何使用的信息:
falcon.HTTPBadGateway
falcon.HTTPBadRequest
falcon.HTTPConflict
falcon.HTTPError
falcon.HTTPForbidden
falcon.HTTPInternalServerError
falcon.HTTPLengthRequired
falcon.HTTPMethodNotAllowed
falcon.HTTPNotAcceptable
falcon.HTTPNotFound
falcon.HTTPPreconditionFailed
falcon.HTTPRangeNotSatisfiable
falcon.HTTPServiceUnavailable
falcon.HTTPUnauthorized
falcon.HTTPUnsupportedMediaType
falcon.HTTPUpgradeRequired
例如,你可以這樣處理沒找到的圖片:
try:
resp.stream = open(image_path, 'rb')
except IOError:
raise falcon.HTTPNotFound()
或者你也可以這樣處理一個(gè)假冒的文件名:
VALID_IMAGE_NAME = re.compile(r'[a-f0-9]{10}\.(jpeg|gif|png)$')
#...
class Item(object):
def __init__(self, storage_path):
self.storage_path = storage_path
def on_get(self, req, resp, name):
if not VALID_IMAGE_NAME.match(name):
raise falcon.HTTPNotFound()
有時(shí)候你可能對獲取拋出異常的類型沒有太多把握碗降。為了解決這個(gè)問題隘竭,F(xiàn)alcon允許創(chuàng)建解決任何錯(cuò)誤類型的自定義處理程序。例如讼渊,如果數(shù)據(jù)庫拋出繼承自清楚的數(shù)據(jù)庫錯(cuò)誤(NiftyDBError)異常动看,我們可以設(shè)置一個(gè)特殊的錯(cuò)誤處理程序去處理對應(yīng)的數(shù)據(jù)庫錯(cuò)誤(NiftyDBError),但是你不必跨多個(gè)響應(yīng)器(respondee)去粘貼復(fù)制你的錯(cuò)誤處理代碼。
查閱關(guān)于falcon.API.add_error_handler
的文檔爪幻,獲取更多這些特性的信息菱皆,使你的代碼盡可能精簡漂亮:
In [7]: help(falcon.API.add_error_handler)
9. 現(xiàn)在該怎么做?
我們友好的社區(qū)可以回答你的問題挨稿,幫助你解決棘手的問題仇轻。
參照:獲取幫助
之前有提到,F(xiàn)alcon的文檔覆蓋面是相當(dāng)廣的奶甘。所以通過Python交互式解釋器(REPL,例如IPython篷店、bpython)查閱Falcon的模塊,你可以學(xué)到很多臭家。
同時(shí)疲陕,千萬不要吝嗇將Github上的Falcon源代碼pull下來,并用你喜歡的編輯器去查看Falcon代碼钉赁。開發(fā)團(tuán)隊(duì)已經(jīng)盡可能將代碼寫的簡潔明了蹄殃、高可讀性;文檔可能會(huì)有些不足,但是代碼基本上不會(huì)出錯(cuò)的你踩。