[Python]在一段Python程式中使用多次事件迴圈

憶先發表於2019-02-16

背景

我們在Python非同步程式編寫中經常要用到如下的結構

import asyncio
async def doAsync():
    await asyncio.sleep(0)
    #...
if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(doAsync())
    loop.close()

這當然是很不錯的,但當你第二次使用loop的時候程式就會丟擲異常RuntimeError: Event loop is closed,這也無可厚非,理想的程式也應該是在一個時間迴圈中解決掉各種非同步IO的問題。
但放在終端環境如Ipython中,如果想要練習Python的非同步程式的編寫的話每次都要重新開啟終端未免太過於麻煩,這時候要探尋有沒有更好的解決方案。

解決方案

我們可以使用asyncio.new_event_loop函式建立一個新的事件迴圈,並使用asyncio.set_event_loop設定全域性的事件迴圈,這時候就可以多次執行非同步的事件迴圈了,不過最好儲存預設的asyncio.get_event_loop並在事件迴圈結束的時候還原回去。
最終我們的程式碼就像這樣。

程式碼

import asyncio
async def doAsync():
    await asyncio.sleep(0)
    #...
def runEventLoop()
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(doAsync())
    loop.close()
if __name__ == "__main__":
    oldloop = asyncio.get_event_loop()
    runEventLoop()
    runEventLoop()
    asyncio.set_event_loop(oldloop)

感想

事件迴圈本來就是要一起做很多事情,在正式的Python程式碼中還是隻用一個預設的事件迴圈比較好,平時的學習練習的話倒是隨意了。

相關文章