協程,又稱微線程,是一種在使用者態進行上下文切換的技術。簡而言之,其實就是透過一個執行緒實作程式碼區塊相互切換執行
Python對協程的支援是透過generator實現的。
在generator中,我們不但可以透過for迴圈來迭代,還可以不斷呼叫next()函數取得由yield語句傳回的下一個值。 Python的yield不僅可用於傳回值,還能接收呼叫者傳遞的參數。
Python中稱為生成器(generator)的機制是一邊循環一邊計算的。透過給定演算法然後在調用的過程中計算真實值。
當需要從generator取得值的時候可以使用next(),但一般會使用for迴圈來取得。
generator的實作方式產生器,使用()表示
如:[1, 2, 3, 4, 5],產生器方法:
data = [1, 2, 3, 4, 5] (x * x for x in len(data))
函數定義在一些邏輯複雜的場景下,使用第一種方法不太合適,因此存在類型函數定義的方式,如:
def num(x): while (x < 10): print(x * x) x += 1 g = num(1) for item in g: print(item)
當函數中出現yield的時候,此時就成為generator
def num(x): while (x < 10): yield x * x # 返回结果,下次从这个地方继续? x += 1 g = num(1) # 返回的是generator对象 for item in g: print(item)
變成generator的函數,在每次呼叫next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。
非同步io透過事件循環和協程函數實現
事件循環即不斷監察內部的任務,如果存在則執行;任務分為可執行和正在執行;由事件循環決定處理任務,如果任務清單為空,事件終止。
import asyncio # 生成或获取事件循环对象loop;类比Java的Netty,我理解为开启一个selector loop = asyncio.get_event_loop() # 将协程函数(任务)提交到事件循环的任务列表中,协程函数执行完成之后终止。 # run_until_complete 会检查协程函数的运行状态,并执行协程函数 loop.run_until_complete( func() )
test demo
import asyncio import time async def test(): print("io等待") await asyncio.sleep(1) return 'hello' async def hello(): print("Hello world") r = await test() print("hello again") loop = asyncio.get_event_loop() tasks = [hello(), hello()] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
協程函數:由async def 修飾的函數;相較於普通的def, 如def func(),可以直接接收到函數傳回的值;但是對於協程函數傳回的是一個協程物件。
想要執行協程函數,需要將這個物件交給事件循環進行處理。
# 测试协程 import asyncio import time, datetime # 异步函数不同于普通函数,调用普通函数会得到返回值 # 而调用异步函数会得到一个协程对象。我们需要将协程对象放到一个事件循环中才能达到与其他协程对象协作的效果 # 因为事件循环会负责处理子程 序切换的操作。 async def Print(): return "hello" loop = asyncio.get_event_loop() loop.run_until_complete(Print)
await:
用法:reponse = await 可等待對象
可等待對象: 協程對象, Future, Task對象可理解為IO等待
response : 等待的結果await 遇到IO操作會掛起目前協程(任務),當前協程掛起時,事件循環可以去執行其他協程(任務) 注意:可等待對象若是協程對象則變成串行,若是Task對象則並發運行Task對象,可以在事件循環列表中新增多個任務。可以使用`asyncio.create_task()`來建立一個`Task`對象,傳遞的參數為協程物件
import asyncio import time, datetime async def display(num): pass tasks = [] for num in range(10): tasks.append(display(num)) # 生成任务列表 loop = asyncio.get_event_loop() loop.run_until_complete(asyncio.wait(tasks))
asnyc和await是新文法,舊版為:@asyncio.coroutine 和yield from
asyncio可以實作單執行緒並發IO操作。如果只用在客戶端,發揮的威力不大。如果把asyncio用在伺服器端,例如Web伺服器,由於HTTP連線就是IO操作,因此可以用單執行緒 coroutine實現多用戶的高並發支援。
aiohttp則是基於asyncio實現的HTTP框架。
可以類似requests發送請求get請求
可以透過params參數來指定要傳遞的參數
async def fetch(session): async with session.get("http://localhost:10056/test/") as response: data = json.loads(await response.text()) print(data["data"])
post請求
非同步的執行兩個任務
在網路請求中,一個請求就是一個會話,然後aiohttp使用的是ClientSession來管理會話
使用session.method發送請求
對於回應訊息response, 透過status來取得回應狀態碼,text()來取得到回應內容;可以在text()指定編碼格式。在等待回應結果前,需要在response.text()前面加上await關鍵字
async def init(num): async with aiohttp.ClientSession() as session: if num == 1: time.sleep(5) print("session begin", num) async with session.post("http://localhost:10056/hello/", data=json.dumps({"data": "hello"})) as response: print("client begin", num) data = json.loads(await response.text()) print(data["data"]) print("session end", num) print("other") if __name__ == '__main__': loop = asyncio.get_event_loop() tasks = [init(1), init(2)] loop.run_until_complete(asyncio.wait(tasks))
以上是Python async模組如何使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!