跳到主要內容

發表文章

目前顯示的是 8月, 2022的文章

[Python] 關於 with 你所不知道的事

相信用 C 語言寫過檔案讀取的人都知道,經常開檔後就忘記關檔,或者程式中間跳出例外,因此沒有關檔。這些問題常常讓人非常頭痛😱。 所幸 Python 中有 with 這個語法糖,可以自動幫你開關檔,跳出例外也難不倒他,真的非常好用。 但你真的了解 with 背後的運行原理嗎? 🤔 不知道沒關係,因為你現在就會知道了! context manager 在講 with 之前,必須先介紹一下 context manager ,中文可以翻成 情境管理器 。 為什麼叫做 情境管理器 呢? 我們試想一個情境… 當你進入房間時,就要開啟房間的燈:然後當你離開房間時,就要關閉房間的燈。 像這樣理所當然一定要做的事情,我們就稱為一個情境。而 Python 就是透過情境管理器處理這些情境。 要自己實作 context manager 其實很簡單,只要在 Class 中實作 __enter__() 和 __exit__() 即可。 就以進入房間當作例子。 class Room (): def turn_on_light ( self ): print ( "開燈" ) def turn_off_light ( self ): print ( "關燈" ) def __enter__ ( self ): print ( "進入房間" ) self.turn_on_light() return "在房間裡" def __exit__ ( self, exc_type, exc_value, traceback ): self.turn_off_light() print ( "離開房間" ) with Room() as room: ...

[Python] async def & await 重點整理

最近實習要用到 FastAPI ,我發現 FastAPI 的 path operation function 會使用 async def ,還會搭配使用 await ,因為對這兩個關鍵字沒很熟,所以就藉機紀錄一下,也避免之後忘記。 async def & await 使用情境 我直接利用下面這個例子來展示什麼情況下可以使用 async 和 await 。 import time def dosomething ( i ): print ( f"第 {i} 次開始" ) time.sleep( 2 ) print ( f"第 {i} 次結束" ) if __name__ == "__main__" : start = time.time() for i in range ( 5 ): dosomething(i+ 1 ) print ( f"time: {time.time() - start} (s)" ) 執行後應該會像這樣。 第 1 次開始 第 1 次結束 第 2 次開始 第 2 次結束 第 3 次開始 第 3 次結束 第 4 次開始 第 4 次結束 第 5 次開始 第 5 次結束 time: 10.048049688339233 (s) 這非常直覺,因為每次呼叫 dosomething() 時都會等待2秒,等完才會執行下一輪,所以最後執行總時間是10秒相當合理。 但仔細想想,如果那2秒是做網路請求或檔案讀寫(IO),這2秒是不需要CPU的,但CPU就只能發呆2秒,痴痴地等待回傳結果,其他什麼事都不能做,豈不是太浪費了嗎!? (學過作業系統的人就知道,絕對不能讓CPU發呆XD) 因此 Python 就有了 asyncio 這個工具,來徹底的利用(X) 榨乾(O) CPU的效能。 我把剛才的例子改成 asyncio 的版本。 import time import asy...