1. 程式人生 > 其它 >Python併發程式設計從入門到進階

Python併發程式設計從入門到進階

本文是Python進階系列專題的最後一篇文章了,學習一下Python併發程式設計。懂得併發程式設計,就算是真正進階了。

Python多執行緒

Python有真正的多執行緒嗎?我本來以為是沒有的。因為CPython直譯器本身就不是執行緒安全的,因此有全域性直譯器鎖(GIL),一次只允許使用一個執行緒執行Python位元組碼。換句話說,Python即便是有多執行緒,也會受GIL限制,按順序執行。所以我就以為Python是沒有多執行緒的,也就是一個Python程序不能同時使用多個CPU核心。然而,Python標準庫中所有執行阻塞型I/O操作的函式,在等待作業系統返回結果時,都會釋放GIL,允許其他執行緒執行

。這就意味著Python執行緒在I/O密集型應用中還是可以發揮作用的,比如一個Python執行緒等待網路響應時,阻塞型I/O函式會釋放GIL,再執行一個執行緒。再比如time.sleep()函式也會釋放GIL。

Python多程序

但是對於CPU密集型應用來說,要想利用所有可用的CPU核心,就得使用多程序,規避GIL。

多執行緒與多程序對比

什麼時候用多執行緒?什麼時候用多程序?

I/O密集型應用使用多執行緒,CPU密集型應用使用多程序。

什麼是I/O密集型應用?什麼是CPU密集型應用?

簡單來說,I/O密集一般涉及到網路、磁碟IO。而CPU密集指的是計算比較多。

建立多執行緒可以使用concurrent.futures,建立多程序可以使用multiprocessing。

多執行緒與協程對比

多執行緒存在著切換開銷,同時為了避免寫變數衝突,在控制共享資源時需要加鎖,因此編寫程式會比較複雜比較困難。而協程是通過單執行緒實現的併發,既能自由切換,也不需要鎖機制,執行效率要高很多。

多執行緒和協程有個共同點是隻對I/O密集型應用有效,因為GIL限制。如果想處理CPU密集型應用,那麼可以結合多程序一起使用,以提高CPU使用率。

asyncio包

asyncio包比較多用來實現Python協程併發,原書在這一章節引用了很多示例,穿插了很多程式碼,導致我看起來有點亂,不是很清楚到底該怎麼使用這個包。所以我看了一下官方文件:

https://docs.python.org/3/library/asyncio.html

從Python3.5開始引入了async和await,替代了@asyncio.coroutine和yield from語法,語義更簡潔更明確了。並且從Python3.7開始引入了asyncio.run(),替代了這一串程式碼:

loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
finally:
    loop.close()

建立task的語法也發生了變化,可以用asyncio.create_task

async def coro():
    ...

# In Python 3.7+
task = asyncio.create_task(coro())
...

# This works in all Python versions but is less readable
task = asyncio.ensure_future(coro())
...

對於多個並行task可以用asyncio.gather,替代asyncio.wait:

task_list = []
    for i in range(5):
        task = asyncio.create_task(async_func(i))
        task_list.append(task)

done, pending = await asyncio.wait(task_list, timeout=None)
for done_task in done:
        print((f"[{current_time()}] 得到執行結果 {done_task.result()}"))
task_list = []
    for i in range(5):
        task = asyncio.create_task(func(i))
        task_list.append(task)
results = await asyncio.gather(*task_list)
for result in results:
        print((f"[{current_time()}] 得到執行結果 {result}"))

所以對於第三方包的學習,最好是看看最新的官方文件,說不定已經進行了很多優化。

最後,完結,撒花。

我會把《流暢的Python》這本書送給大家,感謝一直以來的關注。

參考資料:

《流暢的Python》 第17章使用future處理併發 第18章使用asyncio包處理併發

https://blog.csdn.net/youanyyou/article/details/78990156

https://zhuanlan.zhihu.com/p/104918655

https://www.cnblogs.com/liugp/p/11072823.html

https://www.jianshu.com/p/6872bf356af7


所有文章公眾號首發!
如果你覺得這篇文章寫的還不錯的話,關注公眾號“dongfanger”,你的支援就是我寫文章的最大動力。

版權申明:本文為博主原創文章,轉載請保留原文連結及作者。