本文目錄一覽:
- 1、python協程(4):asyncio
- 2、python協程和異步IO——IO多路復用
- 3、Python怎麼多線程中添加協程?
- 4、python中的協程內部是怎麼實現的
- 5、如何用python寫一個協程
- 6、python協程問題
python協程(4):asyncio
asyncio是官方提供的協程的類庫,從python3.4開始支持該模塊
async awiat是python3.5中引入的關鍵字,使用async關鍵字可以將一個函數定義為協程函數,使用awiat關鍵字可以在遇到IO的時候掛起當前協程(也就是任務),去執行其他協程。
await + 可等待的對象(協程對象、Future對象、Task對象 – IO等待)
注意:在python3.4中是通過asyncio裝飾器定義協程,在python3.8中已經移除了asyncio裝飾器。
事件循環,可以把他當做是一個while循環,這個while循環在周期性的運行並執行一些協程(任務),在特定條件下終止循環。
loop = asyncio.get_event_loop():生成一個事件循環
loop.run_until_complete(任務):將任務放到事件循環
Tasks用於並發調度協程,通過asyncio.create_task(協程對象)的方式創建Task對象,這樣可以讓協程加入事件循環中等待被調度執行。除了使用 asyncio.create_task() 函數以外,還可以用低層級的 loop.create_task() 或 ensure_future() 函數。不建議手動實例化 Task 對象。
本質上是將協程對象封裝成task對象,並將協程立即加入事件循環,同時追蹤協程的狀態。
注意:asyncio.create_task() 函數在 Python 3.7 中被加入。在 Python 3.7 之前,可以改用 asyncio.ensure_future() 函數。
下面結合async awiat、事件循環和Task看一個示例
示例一:
*注意:python 3.7以後增加了asyncio.run(協程對象),效果等同於loop = asyncio.get_event_loop(),loop.run_until_complete(協程對象) *
示例二:
注意:asyncio.wait 源碼內部會對列表中的每個協程執行ensure_future從而封裝為Task對象,所以在和wait配合使用時task_list的值為[func(),func()] 也是可以的。
示例三:
python協程和異步IO——IO多路復用
C10k是一個在1999年被提出來的技術挑戰,如何在一顆1GHz CPU,2G內存,1gbps網絡環境下,讓單台服務器同時為1萬個客戶端提供FTP服務
阻塞式I/O(使用最多)、非阻塞式I/O、I/O復用、信號驅動式I/O(幾乎不使用)、異步I/O(POSIX的aio_系列函數)
select、poll、epoll都是IO多路復用的機制。I/O多路復用就是通過一種機制,一個進程可以監聽多個描述符,一旦,某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程序進行相應的讀寫操作。但select、poll、epoll本質上都是同步I/O,因為他們都需要在讀寫時間就緒後負責進行讀寫,也就是說讀寫過程是阻塞的,而異步I/O無需自己負責進行讀寫,異步I/O的實現會負責把數據從內核拷貝到用戶空間
(1)select
select函數監視的文件描述符分3類,分別是writefds、readfds、exceptfds。調用select函數會阻塞,直到有描述符就緒(有數據可讀、可寫或者有except),或者超時函數返回。當select函數返回後可以通過遍歷fdset來找到就緒的描述符。
select目前幾乎在所有的平台上支持,其良好的跨平台支持也是它的一個優點。select的一個缺點在於單個進程能夠監視的文件描述符的數量存在最大限制,在Linux上一般為1024,可以通過修改宏定義甚至重新編譯內核的方式提升這一限制,但是這樣也會降低效率。
(2)poll
不同於select使用三個位圖來表示三個fdset的方式,poll使用一個pollfd的指針實現。
pollfd結構包含了要監視的event和發生的event,不再使用select”參數-值”傳遞的方式。同時pollfd並沒有最大數量限制(但是數量過大後性能也會下降)。和select函數一樣,poll返回後,需要輪詢pollfd來獲取就緒的描述符。
從上面看,select和poll都需要在返回後通過遍歷文件描述符來獲取已經就緒的socket。事實上同時連接的大量客戶端在同一時刻可能只有很少的處於就緒的狀態,因此隨着監視的描述符數量的增長,其效率也會線性下降
(3)epoll
epoll是在2.6內核中提出的,是之前的select和poll的增強版本。相對於select和poll來說,epoll更加領靈活,沒有描述符限制。epoll使用一個文件描述符管理多個描述符,將用戶關係的文件描述符的事件存放到內核的一個事件表中,這樣在用戶空間和內核空間的copy只需一次。
Python怎麼多線程中添加協程?
由於python是一種解釋性腳本語言,python的多線程在運行過程中始終存在全局線程鎖。
簡單的來說就是在實際的運行過程中,python只能利用一個線程,因此python的多線程並不達到C語言多線程的性能。
可以使用多進程來代替多線程,但需要注意的是多進程最好不要涉及到例如文件操作的頻繁操作IO的功能。
python中的協程內部是怎麼實現的
用yield實現的。。。
def conroutineA():
print “coroutine starts”
while 1:
a = yield
if a % 2 == 0: print a ,”is an even number”
c = coroutineA()
c.next()
c.send(1) #
c.send(2) # …
yield 作為send發送的參數送入,每次執行到yield停止。
第一個next叫做prime。。。就這樣
如何用python寫一個協程
再寫一個任務函數
import asyncio
async def outer():
print(‘in outer’)
print(‘waiting for result1’)
result1 = await phase1()
print(‘waiting for result2’)
result2 = await phase2(result1)
return (result1, result2)
async def phase1():
print(‘in phase1’)
return ‘result1’
async def phase2(arg):
print(‘in phase2’)
return ‘result2 derived from {}’.format(arg)
event_loop = asyncio.get_event_loop()
try:
return_value = event_loop.run_until_complete(outer())
print(‘return value: {!r}’.format(return_value))
finally:
event_loop.close()
python協程問題
你的理解完全錯誤: 1. timeout2秒不是2秒後才有回應,而是超過2秒後沒有回應就會有異常, 你2秒後再回來檢查??
2. 用協程可以寫出異步IO的代碼,一秒1000的並發都沒問題,你根本就沒理解什麼是協程
另外,樓上的回答用多線程或多進程可以做,, 我建議使用多線程完成,,,,,多進程消耗資源太多,而且IO密集型的程序,不需要用到多CPU
原創文章,作者:YXFPM,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/313746.html