使用 voluptuous 校驗資料

yylucifer發表於2016-04-10

在 Python 中,我們經常需要對引數進行校驗,這是我們有好多種方法,例如寫很多 if 啊,或者寫正規表示式啊等等,技巧高的人可以寫得很巧妙,而技巧一般的人呢,可能會寫得很冗長,例如我,經常就不能很好得處理引數校驗的程式碼。

所以我就不斷得尋找,終於最近發現了一個不錯的 python 引數校驗 lib,叫做 voluptuous。名字可能有點難記,而且英文翻譯過來的中文還不怎麼好聽,但是非常好用。下面就逐漸帶大家嘗試一下 voluptuous 庫的妙用。

安裝 voluptuous

要用之前,肯定要先安裝的啦,安裝這一步很簡單,還是按照往常一般使用 pip 搞定。我使用的是當前的最新版 0.8.8:

嘗試 voluptuous

首先,想來一個最為常見的,就是校驗引數的型別,我這裡假設引數都是以 json 格式進行傳遞的,json 格式在 python 中又可以表現為字典(dict),所以這裡就不做區分了。

以官網的日誌為例,使用分頁的引數為例子,校驗引數的型別,首先,我們要求引數的型別,查詢的欄位q必須為字串,分頁大小per_page必須為數字,頁碼page必須為數字。

那麼,使用 voluptuous 後,可以這樣寫:

這就表示了我們剛才的需求:查詢的欄位q必須為字串,分頁大小per_page必須為數字,頁碼page必須為數字。

那麼,現在,假設客戶端傳過來了一組引數:

那麼,我們要怎麼來校驗呢?也很簡單:

這裡可以看到,我們使用客戶端傳遞過來的引數作為引數,呼叫了我們使用既定模板建立的物件,然後直接把他列印出來,如果你跑過這段程式碼,你會發現結果如下:

沒錯, voluptuous 就是將校驗通過的引數返回了。就是這麼簡單。

那這時,你可能要問了,如果校驗不通過的引數怎麼辦,我要怎麼處理,下面就演示一下如果傳遞的引數是:

這樣的話,要怎麼來處理校驗不通過的問題,其實,當校驗不通過的時候,Schema 會丟擲一個異常,然後我們可以通過捕獲這個異常來確定校驗失敗的問題,例如:

當你執行這段程式碼之後,你會發現列印出來的內容是:

我們就知道引數是有問題的,需要客戶端確認。

更進一步

ok,這就是一個簡單的校驗,下面我們進行更復雜的校驗,我們現在不僅要保證引數的型別正確,我們還需要保證查詢引數一定要有,另外兩個引數可有可無。那麼我們可以怎麼做呢?

其實,也很簡單,就是給必須的引數加上一個 Required 關鍵字,例如這樣:

然後,我們可以嘗試一下加入什麼都不傳,會發生什麼事:

很明顯,你跑一遍就知道了,這段程式碼會丟擲這個異常:

這個時候,我們再貪心一點,我們覺得引數必須還不夠,還不能有多餘的引數,什麼引數都塞過來,浪費我記憶體啊,過濾這個應該和剛才的引數必須有一樣簡單吧?

是的,不過這時因為不是對單獨一個引數起作用了,所以需要放在 Schema 的引數裡面,這個引數叫做 extras,例如下面這段就是表示不要多餘的引數:

然後我們嘗試一下:

結果也很簡單:

其實,Schema 預設就是不允許有多餘引數的,如果我們想要多餘的引數,則需要顯式得將這個引數設定為 True,表示允許有多餘的引數。

現在我們已經知道一些用法了,但是,我們覺得只控制型別不夠,我們還想控制一下引數的長度,例如查詢的引數不能超過 10 個字元,那麼樣怎麼做了?

下面這段程式碼就自定義了一個校驗值不能超過 10 個字元的 str 型別:

校驗函式很簡單,接受一個引數,也就是要校驗的值,然後,如果校驗成功就返回這個值,否則就丟擲一個 Invalid 的異常。這樣 Schema 就知道是否校驗通過了。

其實,你可能會想,如果這裡校驗通過後我返回的不是引數的值會怎樣?如果你有這個想法,我很佩服。

確實,如果這裡不返回引數的值,Schema 也會認為是校驗通過的,而且 Schema 會將你的返回值返回。那麼想到這裡,你是不是有一些更加強大的想法?好吧,不知道你有沒有,我這裡告知一下,可以通過這個方法來進行資料轉換。

假如,我們的查詢只支援大寫字母,但是我們認為客戶端傳過來是小寫字母的時候也是有效的,那麼,我們就需要將客戶端傳遞過來的引數進行轉換,轉成大寫字母,那麼,我們可以這樣寫:

然後,我們看一下輸出:

已經變成了大寫了。

好吧,到此已經將 voluptuous 的一些比較常用和重要的功能介紹完了,如果大家有用心去體會的話,相信可以寫出一些非常精妙的校驗器出來。

希望這篇文章對幫助大家理解 voluptuous 有所幫助,謝謝。

相關文章