Python直接改變實例化對象的列表屬性的值 導致在flask中接口多次請求報錯

錯誤原理實例如下:

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/

發佈了92 篇原創文章 · 獲贊 2 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章