點擊python編程從入門到實踐,置頂 公衆號重磅 python入門資料,第一時間送達javascript
仍是牛java
讀完須要python
速讀僅需 4 分鐘程序員
/ python 生產實戰 高效優雅處理程序錯誤 /web
今天,討論一下程序中的錯誤處理。也許你會以爲這個事沒什麼意思,處理錯誤的代碼並不難寫。但你想過沒有,要把錯誤處理寫好,並非件容易的事情。另外,任何一個穩定的程序中都會有大量的代碼在處理錯誤,因此說,處理錯誤是程序中一件比較重要的事情。本篇咱們系統地瞭解一下錯誤處理的各類方式和相關實踐。編程
錯誤是指致使系統不能按照用戶意圖工做的一切緣由、事件。在程序設計過程當中,因爲某些錯誤的存在,導致程序沒法正常運行,處理這些錯誤以使程序正確運行就稱爲錯誤處理。錯誤處理功能是衡量編譯器性能的重要方面,它在幫助程序員儘快修改程序方面起到了很是重要的做用。api
1安全
程序錯誤類型微信
1.1閉包
語法錯誤
語法錯誤是由於源程序中不正確的代碼產生的,即在編寫程序時沒有遵照語法(或詞法)規則,書寫了錯誤的語法代碼,從而致使編譯器沒法正確解釋源代碼而產生的錯誤,一般是因爲錄入的錯誤引發的,它在詞法分析或語法分析時檢測出來。如「非法字符」、「括號不匹配」、「缺乏;」之類的錯誤。
1.2
語義錯誤
語義錯誤是指源程序中不符合語義規則的錯誤,即一條語句試圖執行一條不可能執行的操做而產生的錯誤。語義錯誤有的在語義分析時檢測處來,有的在運行時才能檢測出來。如變量聲明錯誤、做用域錯誤、數據存儲區的溢出等錯誤。
1.3
邏輯錯誤
邏輯錯誤是指程序的運行結果和程序員的設想有出入時產生的錯誤。這類錯誤並不直接致使程序在編譯期間和運行期間出現錯誤,可是程序未按預期方式執行,產生了不正確的運行結果,較難發現。這種錯誤只能經過分析結果,將結果與設計方案進行對比來發現。
2
HTTPException
咱們用 HTTPException 模塊返回帶錯誤信息的 Response。HTTPException 是一個普通的 Python 異常,同時帶有與 API 訪問有關的附加數據。
from fastapi import FastAPI, HTTPException
app = FastAPI()
items = {"book": "Learn Python"}
@app.get("/items/{item_id}")async def read_item(item_id: str): if item_id not in items:
raise HTTPException(status_code=404, detail="Item not found")
return {"item": items[item_id]}
3
添加自定義頭信息
有時候針對 HTTP 錯誤,在一些場景下,咱們須要添加自定義頭信息
from fastapi import FastAPI, HTTPException
app = FastAPI()
items = {"book": "Learn Python"}
@app.get("/items-header/{item_id}")async def read_item_header(item_id: str): if item_id not in items: raise HTTPException( status_code=404, detail="Item not found", headers={"X-Error": "error info"},
) return {"item": items[item_id]}
4
自定義異常處理器
在 fastapi 中藉助 the same exception utilities from Starlette,咱們能夠添加自定義異常處理器。假設咱們有個自定義異常 UnicornException,咱們想在全局範圍內處理這個異常。藉助 @app.exception_handler(),就能夠實現咱們的目標。
from fastapi import FastAPI, Requestfrom fastapi.responses import JSONResponse
class UnicornException(Exception): def __init__(self, name: str): self.name = name
app = FastAPI()
@app.exception_handler(UnicornException)async def unicorn_exception_handler(request: Request, exc: UnicornException):
return JSONResponse( status_code=418, content={"message": f"Oops! {exc.name} did something. error"}, )
@app.get("/get_name_info/{name}")async def read_unicorn(name: str): if name == "haishiniu": raise UnicornException(name=name)
return {"name": name}
5
重寫缺省異常處理器
fastapi 有一些缺省的異常處理器。當咱們拋出 HTTPException 異常或者當請求有非法數據的時候,這些處理器負責返回默認的 JSON 結果。咱們能夠重寫這些異常處理器。
5.1
重寫請求校驗異常處理器
當一個請求包含非法數據的時候,fastapi 內部會拋出 RequestValidationError 異常,而且有默認的異常處理器來處理。咱們能夠用 @app.exception_handler(RequestValidationError) 來重寫這個異常處理器。
from fastapi import FastAPI, HTTPExceptionfrom fastapi.exceptions import RequestValidationErrorfrom fastapi.responses import PlainTextResponsefrom starlette.exceptions import HTTPException as StarletteHTTPException
app = FastAPI()
@app.exception_handler(StarletteHTTPException)async def http_exception_handler(request, exc): return PlainTextResponse(str(exc.detail), status_code=exc.status_code)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc): return PlainTextResponse(str(exc), status_code=400)
@app.get("/items/{item_id}")async def read_item(item_id: int): if item_id == 3: raise HTTPException(status_code=418, detail="Nope! I don't like 3.") return {"item_id": item_id}
5.2
重寫 HTTPException 異常處理器
一樣的方法,咱們能夠重寫 HTTPException 異常處理器。例如,你可能想返回純文本格式而不是 JSON 格式的錯誤信息。
from fastapi import FastAPI, HTTPExceptionfrom fastapi.exceptions import RequestValidationErrorfrom fastapi.responses import PlainTextResponsefrom starlette.exceptions import HTTPException as StarletteHTTPException
app = FastAPI()
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(request, exc):
return PlainTextResponse(str(exc.detail), status_code=exc.status_code)
@app.exception_handler(RequestValidationError)async def validation_exception_handler(request, exc): return PlainTextResponse(str(exc), status_code=400)
@app.get("/items/{item_id}")async def read_item(item_id: int): if item_id == 3:
raise HTTPException(status_code=418, detail="Nope! I don't like 3.")
return {"item_id": item_id}
5.3
重用缺省異常處理器
咱們能夠導入而且重用缺省的異常處理器。咱們從 fastapi.exception_handlers 導入缺省異常處理器。
from fastapi import FastAPI, HTTPExceptionfrom fastapi.exception_handlers import ( http_exception_handler, request_validation_exception_handler,)
from fastapi.exceptions import RequestValidationErrorfrom starlette.exceptions import HTTPException as StarletteHTTPException
app = FastAPI()
@app.exception_handler(StarletteHTTPException)async def custom_http_exception_handler(request, exc): print(f"OMG! An HTTP error!: {repr(exc)}") return await http_exception_handler(request, exc)
@app.exception_handler(RequestValidationError)async def validation_exception_handler(request, exc): print(f"OMG! The client sent invalid data!: {exc}") return await request_validation_exception_handler(request, exc)
@app.get("/items/{item_id}")async def read_item(item_id: int): if item_id == 3: raise HTTPException(status_code=418, detail="Nope! I don't like 3.") return {"item_id": item_id}
在示例中,咱們在拋出異常以前添加了一條日誌輸出。咱們能夠根據業務需求靈活的重用缺省異常處理器。
6
fastapi HTTPException 對比 Starlette HTTPException
fastapi 中 HTTPException 繼承自 Starlette 的 HTTPException。
惟一的區別 fastapi 中 HTTPException 容許你在 response 添加頭信息。主要在內部用於 OAuth 2.0 以及一些安全相關的功能。
所以,一般咱們在代碼中拋出 fastapi 的 HTTPException 異常。可是,當咱們註冊異常處理器的時候,咱們應該註冊爲 Starlette 的 HTTPException。這樣,當 Starlette 的內部代碼或者 Starlette 擴展插件拋出 Starlette HTTPException 時,咱們的處理器才能正常捕獲和處理這個異常。若是咱們要在代碼中同時使用這兩個類,爲了不命名衝突,咱們能夠重命名其中一個類。
7
總結
1.介紹了 什麼是錯誤以及錯誤的分類信息
2.在 fastapi 中是如何自定義異常處理
原創不易,只願能幫助那些須要這些內容的同行或剛入行的小夥伴,你的每次 點贊、分享 都是我繼續創做下去的動力,我但願能在推廣 python 技術的道路上盡我一份力量,歡迎在評論區向我提問,我都會一一解答,記得一鍵三連支持一下哦!
加入python學習交流微信羣,請後臺回覆「入羣」
往期推薦
本文分享自微信公衆號 - python編程軍火庫(PythonCoder1024)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。