我正在開發一個 Flask API,它將從云資料庫中讀取資料。
我在錯誤處理中注意到了一些奇怪的行為。
當我發出回傳錯誤的請求,然后發出正確的請求時,錯誤json將在正確的請求中再次回傳。但是只有在主體中,API 狀態代碼是正確的(并且flask 應用程式根本不會拋出錯誤,實際上它甚至似乎沒有呼叫錯誤處理模塊)。
如果我將錯誤從例如無效的 queryparam 請求更改為 404 請求,錯誤將在 json 中更改,并且回傳的最新錯誤將在所有后續請求中持續存在,直到我重新運行應用程式。
我在我的應用程式中注冊了一個錯誤處理模塊:
from server.errorhandling.errors import InvalidQueryParameterError
from flask import Blueprint, jsonify, request
from server.common.jsonresponse import set_error_jsonresponse
import traceback
handle_errors = Blueprint('errorhandler', __name__)
@handle_errors.app_errorhandler(InvalidQueryParameterError)
def handle_notfound_error(error):
traceback.print_exc()
message = [str(x) for x in error.args]
status_code = 400
response = set_error_jsonresponse(message,error.__class__.__name__)
return jsonify(response), status_code
@handle_errors.app_errorhandler(404)
def handle_notfound_error(error):
traceback.print_exc()
message = [str(x) for x in error.args]
status_code = 404
response = set_error_jsonresponse(message,error.__class__.__name__)
return jsonify(response), status_code
在我的應用程式中注冊:
self.register_blueprint(errorhandler.handle_errors)
我有一個用于設定 json 回應的模塊,“正常”成功回應代碼和錯誤處理都使用它:
from flask import current_app,request,Blueprint
# - Static template for response json -
response_body = {
"domain": {
"datatype": {
"data": {
}
}
}
}
def set_jsonresponse(query_jobs):
for job in query_jobs:
response_tuple = queryjob_to_response_tuple(job)
response_data = response_tuple
response_obj = DataResponse(response_data)
response_body['domain']['datatype']['data'][get_data_entity_kvm(response_obj)[0]] = get_data_entity_kvm(response_obj)[1]
success_response_body = response_body
return success_response_body
def set_error_jsonresponse(message="An unexpected error has occurred.",errortype="InternalError"):
error_body = {
"error":{
"message":message,
"type":errortype
}
}
response_body['domain']['datatype'].update(error_body)
return response_body
其他一切似乎都按預期作業。當我除錯代碼時,問題出現在我設定 response_body 的行中。但我不認為我如何在代碼中設定回應本身就是問題,我懷疑問題更多地與我尚未理解的回應資料的一些后臺存盤有關。
雖然問題很相似,但我在這里嘗試了答案: API 在flask 中提供舊回應, 但它不起作用。我已經嘗試過發送 no-cache 標頭值并在我的應用程式中對它們進行硬編碼。
我沒有得到什么?
uj5u.com熱心網友回復:
您正在定義response_body為全域變數。
# - Static template for response json -
response_body = {
"domain": {
"datatype": {
"data": {
}
}
}
}
在set_error_jsonresponse呼叫中,您更新此全域變數,然后回傳它:
response_body['domain']['datatype'].update(error_body)
存盤在此結構中的任何資料在后續請求中仍然存在,因為全域變數在作業執行緒的記憶體中。
我不確定是什么get_data_entity_kvm,但它看起來像在set_jsonresponse您再次編輯全域的函式中,而不洗掉error_body之前添加的那個。
response_body['domain']['datatype']['data'][get_data_entity_kvm(response_obj)[0]] = get_data_entity_kvm(response_obj)[1]
因此,即使在隨后的成功請求中,也會看到來自最后一個請求的錯誤訊息。狀態代碼是正確的,因為它們是在處理程式函式中定義的。當您重新啟動應用程式時,response_body將設定回原始狀態。
對此的快速解決方法不是定義response_body為全域。所以你可以有這樣的功能:
def get_response_body():
return {
"domain": {
"datatype": {
"data": {
}
}
}
}
然后在需要它的每個函式中,例如:
def set_error_jsonresponse(message="An unexpected error has occurred.",errortype="InternalError"):
response_body = get_response_body()
# do something with that...
我還建議研究 Flask 部署檔案,并了解 WSGI 服務器。在生產設定中,像 WSGI 服務器gunicorn可能有幾個同步的作業人員。在該配置中,從該應用程式觀察到的行為會更加奇怪:與您現在看到的相同,但不一致,因為后續請求可能由多個作業人員中的任何一個處理,每個作業人員都有自己的response_body全域副本. 這是因為全域變數不是執行緒安全的。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/386200.html
上一篇:如何找到方法來自的模塊/類?
