Falcon教程

Falcon Tutorial(英文鏈接)

標(biāo)簽: 'REST' 'Falcon' 'Python'


1. 整體架構(gòu)(The Big Picture)

架構(gòu)圖
架構(gòu)圖

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簽名芜辕。envstart_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í)慣,我們一般寫作reqresp扶檐。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_headerresp.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.bodyresp.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)的reqreqsp對象狸相,作為前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.beforefalcon.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ò)的你踩。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诅岩,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子带膜,更是在濱河造成了極大的恐慌吩谦,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件膝藕,死亡現(xiàn)場離奇詭異逮京,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)束莫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門懒棉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來草描,“玉大人,你說我怎么就攤上這事策严∷肽剑” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵妻导,是天一觀的道長逛绵。 經(jīng)常有香客問我,道長倔韭,這世上最難降的妖魔是什么术浪? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮寿酌,結(jié)果婚禮上胰苏,老公的妹妹穿的比我還像新娘。我一直安慰自己醇疼,他們只是感情好硕并,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秧荆,像睡著了一般倔毙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乙濒,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天陕赃,我揣著相機(jī)與錄音,去河邊找鬼颁股。 笑死么库,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的豌蟋。 我是一名探鬼主播廊散,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼桑滩,長吁一口氣:“原來是場噩夢啊……” “哼梧疲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起运准,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤幌氮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后胁澳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體该互,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年韭畸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宇智。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蔓搞。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖随橘,靈堂內(nèi)的尸體忽然破棺而出喂分,到底是詐尸還是另有隱情,我是刑警寧澤机蔗,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布蒲祈,位于F島的核電站,受9級(jí)特大地震影響萝嘁,放射性物質(zhì)發(fā)生泄漏梆掸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一牙言、第九天 我趴在偏房一處隱蔽的房頂上張望酸钦。 院中可真熱鬧,春花似錦嬉挡、人聲如沸钝鸽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拔恰。三九已至,卻和暖如春基括,著一層夾襖步出監(jiān)牢的瞬間颜懊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工风皿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留河爹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓桐款,卻偏偏與公主長得像咸这,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子魔眨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理媳维,服務(wù)發(fā)現(xiàn),斷路器遏暴,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,809評論 6 342
  • Hadoop的元數(shù)據(jù)治理--Apache Atlas Apache Atlas是Hadoop社區(qū)為解決Hadoop...
    小白_18M閱讀 54,840評論 12 43
  • 一侄刽、概念(載錄于:http://www.cnblogs.com/EricaMIN1987_IT/p/3837436...
    yuantao123434閱讀 8,353評論 6 152
  • 孤獨(dú)往往是自己最不想的,可有什么辦法呢朋凉? 孤獨(dú)一般來自情侶分手后的情感州丹,來自同學(xué)的嘲笑和譏諷,來自自己是無助的時(shí)候...
    藝a玲閱讀 225評論 0 1