Python requests response的一個地雷

less than 1 minute read

最近在使用Requests踩到一個雷……

使用情境是這樣的,在執行某一段code的時候,需要去打某個API endpoint,但這個endpoint不是required,但如果endpoint存在且回傳409,就要raise error。整段的邏輯大概像這樣:

import requests

def request_to_endpoint():
  url := config.get("endpoint_url")
  if not url:
    return None

  payload = {...}
  return requests.post(url, data=payload)

def main_function():
  res = request_to_endpoint()

  if res and res.status_code == 409:
    raise exception("oops")

  # do some thing
  ...

在寫unit test的時候,也有mock requests.post,來模擬response是409的狀況,也都通過測試,結果上到staging環境被其它team反應 do some thing那塊還是被執行了……

最一開始的反應是會不會endpoint的團隊不講武德,說好了要回409但是沒有回,不過log顯示endpoiont回409無誤,那為何沒有進if block呢?

後來在stackoverflow看到有人說,Requests的Response class override __bool__,只要是400以上就會回傳False…..

老實說,這點真的蠻雷的,無法理解為什麼要這樣設計,也許這樣要判斷是不是合格的response很簡便,但很明顯違反The Zen of Python裡面的:

Explicit is better than implicit.

就這點來說,Golang zero value的設計要好得多,因為zero value已經被定義了,要檢查是不是zero value的檢查就沒有模糊空間。

Updated: