程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python async模塊使用(雜文)

編輯:Python

提示:文章寫完後,目錄可以自動生成,如何生成可參考右邊的幫助文檔

文章目錄

  • 一、什麼是 generator(生成器)?
    • generator的實現方式
  • 二、使用asyncio 實現異步io
  • 三、aiohttp


協程:協程(Coroutine),也可以被稱為微線程,是一種用戶態內的上下文切換技術。簡而言之,其實就是通過一個線程實現代碼塊相互切換執行

Python對協程的支持是通過generator實現的。
在generator中,我們不但可以通過for循環來迭代,還可以不斷調用next()函數獲取由yield語句返回的下一個值。
但是Python的yield不但可以返回一個值,它還可以接收調用者發出的參數。

一、什麼是 generator(生成器)?

在Python中,這種一邊循環一邊計算的機制,稱為生成器:generator。通過給定一個算法然後在調用的過程中計算真實值。
當需要從generator中獲取值的時候可以使用next(),但是一般使用for循環進行獲取。

generator的實現方式

  1. 生成器,使用()表示
    如:[1, 2, 3, 4, 5],生成器方法:
data = [1, 2, 3, 4, 5]
(x * x for x in len(data))
  1. 函數定義
    在一些邏輯復雜的場景下,使用第一種方法不太合適,因此存在類型函數定義的方式,如:
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語句處繼續執行。

二、使用asyncio 實現異步io

異步io通過事件循環和協程函數實現
    事件循環即不斷監察內部的任務,如果存在則執行;任務分為可執行和正在執行;由事件循環決定處理任務,如果任務列表為空,事件終止。

import asyncio
# 生成或獲取事件循環對象loop
loop = asyncio.get_event_loop()
# 將協程函數(任務)提交到事件循環的任務列表中,協程函數執行完成之後終止。
# run_until_complete 會檢查協程函數的運行狀態,並執行協程函數
loop.run_until_complete( func() )

    協程函數:由 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

三、aiohttp

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請求
  1. 異步的執行兩個任務
  2. 在網絡請求中,一個請求就是一個會話,然後aiohttp使用的是ClientSession來管理會話
  3. 使用session.method發送請求
  4. 對於響應信息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))


繼續積累。。。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved