協程
- 使用
- 方法一
- 方法二
- 網頁下載中使用
- 有返回值
- 實戰
- 圖片實戰
一個線程多個任務,線程由操作系統開啟,比較耗資源。線程內合理分配任務,充分利用線程內的資源,一個任務io阻塞時,cpu處理其他非阻塞任務。
使用
方法一
import asyncio
# 函數前加async后,成為協程對象
async def as_func():print('協程基本使用')
if __name__ == '__main__':# 1 創建一個協程對象async_obj = as_func()print(async_obj)# 2 創建事件循環event_loop = asyncio.get_event_loop()# 3 執行協程對象event_loop.run_until_complete(async_obj)
方法二
- 可能報RuntimeError: Event loop is closed
import asyncio
# 函數前加async后,成為協程對象
async def as_func():print('協程基本使用')
if __name__ == '__main__':# 1 創建一個協程對象async_obj = as_func()print(async_obj)# 2 執行協程asyncio.run(async_obj)
網頁下載中使用
import asyncio
# 函數前加async后,成為協程對象
async def as_download(url, t):print(url + '協程下載')await asyncio.sleep(t)print(url + '下載完成')async def main():urls = ['url1','url2','url3','url4',]as_tasks = []for url in urls:as_task = asyncio.create_task(as_download(url, 2))as_tasks.append(as_task)await asyncio.wait(as_tasks)if __name__ == '__main__':asyncio.run(main())
有返回值
- wait和gather
import asyncio
async def as_download1():print("協程1開始")await asyncio.sleep(1)print("協程1完成")return "協程1返回"
async def as_download2():print("協程2開始")await asyncio.sleep(2)print("協程2完成")return "協程2返回"
async def as_download3():print("協程3開始")await asyncio.sleep(3)print("協程3完成")return "協程3返回"
async def main():tasks = [asyncio.create_task(as_download3()),asyncio.create_task(as_download1()),asyncio.create_task(as_download2()),]# 取返回值一, wait, 返回的結果是set集合,無序result, pending = await asyncio.wait(tasks)for res in result:print(res.result())print("--以上是隨機順序--"*3)print("--以下是與任務相同順序--"*3)# 取返回值二, gather, 同map一樣,返回的結果的順序與任務順序一致# return_exceptions=True,即使有錯誤,任務正常執行,返回錯誤信息# return_exceptions=False,如果有錯誤,程序報錯,任務停止result = await asyncio.gather(*tasks, return_exceptions=True)for res in result:print(res)
if __name__ == '__main__':asyncio.run(main())
實戰
- aiohttp和aiofiles安裝
pip install aiohttp
pip install aiofiles
圖片實戰
鏈接: url_list
鏈接: url_list
鏈接: url_list
import aiohttp
import asyncio
import aiofiles
async def pic_download(url):try:name = url.split("/")[-1]# 創建session對象 with使用完后自行關閉async with aiohttp.ClientSession() as session:# 發送請求url請求async with session.get(url) as resp:# content.read()讀取圖片數據# resp.text()讀取源代碼即可content = await resp.content.read()# 寫入文件會阻塞, 用aiofiles提升效率async with aiofiles.open(name, mode="wb") as f:await f.write(content)return "finish complete"except:print('報錯')return "failure"
async def main():url_list = ["","","","","",]tasks = []for url in url_list:# 創建任務task = asyncio.create_task(pic_download(url))tasks.append(task)await asyncio.wait(tasks)
if __name__ == '__main__':# asyncio.run(main()) 此句與下2句等同,但在一些版本中報錯loop = asyncio.get_event_loop()loop.run_until_complete(main())