錯誤原理實例如下:
class One(): list = [1, 2, 3] @classmethod def get_copy_list(cls): # copy一份list,這樣對list的改變不會影響到此對象的list return cls.list[:] @classmethod def get_list(cls): # 直接返回此對象的list,任何對list的操作都會影響到此對象的list return cls.list if __name__ == '__main__': # 不影響到One對象的list值 a = One.get_copy_list() print(a) # [1, 2, 3] a.append(4) print(a) # [1, 2, 3, 4] print(One.get_list()) # [1, 2, 3] # 影響到One對象的list值 b = One.get_list() print(b) # [1, 2, 3] b.append(5) print(b) # [1, 2, 3, 5] print(One.get_list()) # [1, 2, 3, 5]
解決方法:調用One.get_copy_list()
在flask中,知識點:一個請求 在進入到進程後,會從進程 App中生成一個新的app(在線程中的應用上下文,改變其值會改變進程中App的相關值,也就是進程App的指針引用,包括g,),以及生成一個新的請求上下文(包括session,request)。並把此次請求需要的應用上下文和請求上下文通過dict格式傳入到 棧中(從而保證每個請求不會混亂)。並且在請求結束後,pop此次的相關上下文。
錯誤接口代碼大致如下:
class
Model_table
(_ModelPub, DB.Model):
__tablename__ = 'recruit_info'
__keys_map__ = {
'info': [
'uid', 'back_img', 'user_name', 'gender', 'age'
]
@Recruit.route('/update_info/<string:action>', methods=['POST']) info_list = Model_table.__keys_map__['info'] info_list += ['img_id', 'prience_id'] print(info_list)
響應如下(每次請求,都會向model類的列表屬性值添加元素,這樣會隨着時間的增長導致內存消耗越來越大,最終導致服務崩潰):
解決方法:
@Recruit.route('/update_info/<string:action>', methods=['POST']) info_list = Model_table.__keys_map__['info'][:] #copy一份list即可 info_list += ['img_id', 'prience_id'] print(info_list)
效果顯示(每個請求不會混亂):
總結:剛開始以爲 在一次請求過程中,無論怎麼操作都不會影響到其他請求的執行,當時只考慮了在 請求上下文中不會出現這種問題,但是 應用上下文,是 進程App相關屬性或常量的一個引用(相當於指針),任何對應用上下文中的改變(g會在每次請求到來時從新賦值,然後在請求結束後跟隨應用上下文,請求上下文一起消失),都會影響到其他請求的執行。
相關連接:
https://blog.tonyseek.com/post/the-context-mechanism-of-flask/