Python 異步編程介紹與代碼示例

Python 異步編程介紹與代碼示例

一、異步編程概述

異步編程是一種編程范式,它旨在處理那些需要等待I/O操作完成或執行耗時任務的情況。在傳統的同步編程中,代碼會按照順序逐行執行,直到遇到一個耗時操作,它會阻塞程序的執行直到該操作完成。這種阻塞式的模型在某些場景下效率低下,因為代碼在等待操作完成時無法執行其他任務。異步編程通過非阻塞I/O和協程(coroutine)來提高效率,使得程序在等待某些操作時能夠繼續執行其他任務,從而提高程序的并發性和響應性。

二、Python 異步編程基礎

Python 從 3.4 版本開始引入了 asyncio 庫,為異步編程提供了豐富的支持。asyncio 庫包括了協程、事件循環(event loop)、任務(task)和期物(future)等關鍵概念。

  1. 協程(Coroutine)
    協程是一種特殊的函數,可以在執行過程中暫停和恢復。在 Python 中,協程是通過在函數定義前加上 async 關鍵字來創建的。協程內部可以使用 await 關鍵字來暫停自身的執行,等待其他協程或異步操作完成。

  2. 事件循環(Event Loop)
    事件循環是異步編程的核心,它負責調度和執行協程,確保它們按照正確的順序執行。在 Python 中,asyncio 模塊提供了事件循環的實現,開發者可以通過 asyncio.get_event_loop() 獲取默認的事件循環對象,并使用它來運行協程。

  3. 任務(Task)
    任務是 asyncio 庫中的一個基本概念,它表示一個異步操作。任務可以通過調用 asyncio.create_task() 函數來創建,并返回一個 Task 對象。Task 對象本質上是一個特殊的 Future 對象,它封裝了協程的執行。

  4. 期物(Future)
    期物用于承載協程的執行結果。當協程開始執行時,會創建一個 Future 對象與之關聯。協程執行完成后,其結果會被存儲在 Future 對象中。開發者可以通過 await 關鍵字等待 Future 對象的結果。

三、async/await 語法

從 Python 3.5 版本開始,可以使用 asyncawait 關鍵字來編寫異步代碼。async 關鍵字用于定義一個協程函數,而 await 關鍵字用于在協程中暫停執行,等待其他協程或異步操作完成。

示例 1:簡單的異步函數
import asyncioasync def my_coroutine():print("Coroutine started")await asyncio.sleep(1)  # 模擬異步操作print("Coroutine resumed")return "Result"async def main():result = await my_coroutine()print(f"Result: {result}")asyncio.run(main())

在這個示例中,my_coroutine 是一個協程函數,它使用 await asyncio.sleep(1) 來模擬一個耗時操作。main 函數也是一個協程函數,它使用 await 關鍵字等待 my_coroutine 的執行結果。最后,通過 asyncio.run(main()) 啟動事件循環,并運行 main 協程。

示例 2:并發執行多個異步任務
import asyncioasync def task(name, delay):print(f"Executing task: {name}")await asyncio.sleep(delay)print(f"Task {name} finished")async def main():tasks = [task("Task 1", 2), task("Task 2", 1), task("Task 3", 3)]await asyncio.gather(*tasks)asyncio.run(main())

在這個示例中,我們定義了三個異步任務 task,每個任務都有一個名稱和延遲時間。在 main 函數中,我們使用 asyncio.gather(*tasks) 來并發執行這些任務。asyncio.gather 會等待所有傳入的協程或任務完成,并返回一個包含所有結果的列表。

四、異步編程的優勢
  1. 提高程序效率
    異步編程通過非阻塞I/O和并發執行多個任務,減少了程序在等待操作完成時的空閑時間,從而提高了程序的執行效率。

  2. 提高程序響應性
    在Web服務器、數據庫連接等場景中,異步編程能夠更快地響應客戶端的請求,提升用戶體驗。

  3. 簡化復雜邏輯
    異步編程通過協程和事件循環等機制,使得處理復雜邏輯(如回調地獄)變得更加簡單和直觀。

五、異步編程的注意事項

在進行Python異步編程時,需要注意以下幾個方面,以確保代碼的正確性、效率和可維護性:

  1. 避免阻塞操作
    異步編程的核心優勢在于非阻塞I/O,因此應盡量避免在協程中執行阻塞操作。如果必須執行阻塞操作,可以通過asyncio.run_in_executor()方法將其封裝在executor中執行,從而避免阻塞事件循環。

  2. 異常處理
    異步編程中的異常處理需要格外小心。由于異步操作可能在將來的某個時間點完成,因此應使用try-except語句來捕獲和處理可能的異常。此外,asyncio還提供了asyncio.ensure_future()函數,可以將協程封裝為Future對象,從而更方便地處理異常。

  3. 并發度控制
    通過控制并發度,可以平衡程序的性能和資源消耗。如果并發任務過多,可能會導致資源耗盡或性能下降。可以使用asyncio.Semaphore等同步原語來限制同時執行的任務數量,從而避免這種情況的發生。

  4. 共享資源訪問
    在異步編程中,多個協程可能會同時訪問共享資源,這可能導致數據競爭和狀態不一致的問題。為了避免這種情況,應使用適當的同步機制(如鎖、信號量等)來保護共享資源。

  5. 事件循環的管理
    在Python的異步編程中,事件循環是核心組件。它負責調度和執行協程,以及處理I/O和系統事件。通常,應使用asyncio.run()函數來啟動和管理事件循環,因為它會自動創建事件循環、運行協程并關閉事件循環。除非有特定需求,否則應避免手動創建和管理事件循環。

  6. 協程的調度和取消
    在復雜的異步程序中,可能需要動態地調度和取消協程。asyncio提供了asyncio.create_task()函數來創建任務(即協程的封裝),并提供了任務對象的方法來檢查任務狀態、取消任務等。

  7. 調試和日志記錄
    異步編程的調試可能比同步編程更復雜,因為程序的執行流程是非線性的。因此,應使用適當的調試工具和日志記錄來跟蹤程序的執行和定位問題。

  8. 第三方庫和框架的兼容性
    在使用異步編程時,可能會遇到與第三方庫和框架的兼容性問題。一些庫可能不支持異步操作,或者它們的異步API不夠完善。在這種情況下,需要仔細評估是否可以使用這些庫,或者尋找替代方案。

  9. 性能優化
    異步編程雖然可以提高程序的并發性和響應性,但也可能引入額外的性能開銷。例如,過多的上下文切換和鎖競爭都可能導致性能下降。因此,在進行異步編程時,應注意性能優化,避免不必要的開銷。

  10. 代碼的可讀性和可維護性
    異步代碼的可讀性和可維護性通常比同步代碼更差,因為異步邏輯更復雜且更難跟蹤。因此,在編寫異步代碼時,應注意代碼的清晰性和結構性,避免過度復雜和難以理解的代碼。

通過遵循上述注意事項,可以更有效地利用Python的異步編程能力,編寫出高效、可靠和可維護的異步應用程序。

六、異步編程中的錯誤處理

在異步編程中,錯誤處理是一個重要的方面。由于異步操作可能在將來的某個時間點完成,并且可能成功或失敗,因此我們需要一種機制來捕獲和處理這些錯誤。

示例 3:異步錯誤處理
import asyncioasync def risky_operation():# 假設這是一個可能引發異常的異步操作await asyncio.sleep(1)raise ValueError("Something went wrong!")async def main():try:await risky_operation()except ValueError as e:print(f"Caught an exception: {e}")asyncio.run(main())

在這個示例中,risky_operation 是一個可能拋出異常的異步函數。在 main 函數中,我們使用 try-except 塊來捕獲并處理這個異常。

七、異步上下文管理器

在 Python 中,上下文管理器(通過 with 語句使用)常用于資源管理,如文件操作、數據庫連接等。在異步編程中,我們也有異步上下文管理器的需求。

從 Python 3.7 開始,asyncio 庫引入了 async with 語法,允許我們使用異步上下文管理器。

示例 4:異步上下文管理器
import asyncioclass AsyncContextManager:async def __aenter__(self):print("Entering context")# 初始化代碼,如打開數據庫連接return selfasync def __aexit__(self, exc_type, exc_val, exc_tb):print("Exiting context")# 清理代碼,如關閉數據庫連接return False  # 如果需要抑制異常,則返回 Trueasync def main():async with AsyncContextManager():print("Inside the context")await asyncio.sleep(1)asyncio.run(main())

在這個示例中,AsyncContextManager 類定義了異步上下文管理器的行為。__aenter__ 方法在進入上下文時執行,__aexit__ 方法在退出上下文時執行。注意,__aexit__ 方法必須返回一個布爾值,用于指示是否需要抑制異常。

八、異步編程與并發

雖然異步編程和并發編程經常一起討論,但它們并不完全相同。異步編程主要關注于單個線程內的非阻塞操作,而并發編程則涉及多個線程或進程同時執行多個任務。然而,在 Python 的 asyncio 庫中,我們可以通過異步編程實現并發效果,因為事件循環能夠同時調度多個協程的執行。

九、高級話題:異步生成器

Python 3.6 引入了異步生成器(async generators),它們是結合了異步編程和生成器特性的強大工具。異步生成器允許你編寫一個可以異步產生值的函數,這些值可以在需要時逐個獲取,而無需一次性加載到內存中。

示例 5:異步生成器
import asyncioasync def async_generator():for i in range(5):await asyncio.sleep(1)  # 模擬異步操作yield iasync def main():async for value in async_generator():print(value)asyncio.run(main())

在這個示例中,async_generator 是一個異步生成器函數,它使用 yield 關鍵字來異步產生值。在 main 函數中,我們使用 async for 循環來逐個獲取這些值。

十、總結

Python 的異步編程通過 asyncio 庫提供了強大的支持,使得編寫高效、響應迅速的異步應用程序成為可能。通過協程、事件循環、任務和期物等概念,Python 的異步編程模型能夠處理復雜的異步邏輯,并優化程序的執行效率。然而,異步編程也帶來了一些挑戰,如錯誤處理和并發控制等。通過深入學習這些概念,并結合實際的應用場景,我們可以更好地利用 Python 的異步編程能力來構建高效、可靠的應用程序。

以上就是對 Python 異步編程的一個基本介紹和代碼示例。希望這些信息能夠幫助你理解并掌握 Python 的異步編程技術。

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/41837.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41837.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/41837.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Codeforces Round 903 (Div. 3)A~F

A.Dont Try to Count 輸入樣例: 12 1 5 a aaaaa 5 5 eforc force 2 5 ab ababa 3 5 aba ababa 4 3 babb bbb 5 1 aaaaa a 4 2 aabb ba 2 8 bk kbkbkbkb 12 2 fjdgmujlcont tf 2 2 aa aa 3 5 abb babba 1 19 m mmmmmmmmmmmmmmmmmmm輸出樣例: 3 1 2 -1 1 0…

1999-2022年企業持續綠色創新水平數據

企業持續綠色創新水平數據為研究者提供了評估企業在綠色技術領域創新持續性和能力的重要視角。以下是對企業持續綠色創新水平數據的介紹: 數據簡介 定義:企業持續綠色創新水平反映了企業在一定時期內綠色專利申請的持續性和創新能力。計算方法&#xf…

初識STM32:開發方式及環境

STM32的編程模型 假如使用C語言的方式寫了一段程序,這段程序首先會被燒錄到芯片當中(Flash存儲器中),Flash存儲器中的程序會逐條的進入CPU里面去執行。 CPU相當于人的一個大腦,雖然能執行運算和執行指令,…

通信協議:常見的芯片內通信協議

相關閱讀 通信協議https://blog.csdn.net/weixin_45791458/category_12452508.html?spm1001.2014.3001.5482 本文將簡單介紹一些常見的芯片間通信協議,但不會涉及到協議的具體細節。 一、AMBA(Advanced Microcontroller Bus Architecture)…

MySQL之備份與恢復(七)

備份與恢復 文件系統快照 規劃LVM備份 LVM快照備份也是有開銷的。服務器寫到原始卷的越多,引發的額外開銷也越多。當服務器隨機修改許多不同塊時,磁頭需要需要自寫時復制空間來來回回尋址,并且將數據的老版本寫到寫時復制空間。從快照中讀…

刷題之多數元素(leetcode)

多數元素 哈希表解法&#xff1a; class Solution { public:/*int majorityElement(vector<int>& nums) {//map記錄元素出現的次數&#xff0c;遍歷map&#xff0c;求出出現次數最多的元素unordered_map<int,int>map;for(int i0;i<nums.size();i){map[nu…

最適合mysql5.6安裝的linux版本-實戰

文章目錄 一, 適合安裝mysql5.6的linu版本1. CentOS 72. Ubuntu 14.04 LTS (Trusty Tahr)3. Debian 8 (Jessie)4. Red Hat Enterprise Linux (RHEL) 7 二, 具體以Ubuntu 14.04 LTS (Trusty Tahr)為例安裝虛擬機安裝Ubuntu 14.04 LTS (Trusty Tahr) 自己弄安裝ssh(便于遠程訪問,…

前端八股文 對$nextTick的理解

$nexttick是什么? 獲取更新后的dom內容 為什么會有$nexttick ? vue的異步更新策略 (這也是vue的優化之一 要不然一修改數據就更新dom 會造成大量的dom更新 浪費性能) 這是因為 message &#xff08;data&#xff09;數據在發現變化的時候&#xff0c;vue 并不會立刻去更…

240705_昇思學習打卡-Day17-基于 MindSpore 實現 BERT 對話情緒識別

240705_昇思學習打卡-Day17-基于 MindSpore 實現 BERT對話情緒識別 近期確實太忙&#xff0c;此處僅作簡單記錄&#xff1a; 模型簡介 BERT全稱是來自變換器的雙向編碼器表征量&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff0c…

【wordpress教程】wordpress博客網站添加非法關鍵詞攔截

有的網站經常被惡意搜索&#xff0c;站長們不勝其煩。那我們如何屏蔽惡意搜索關鍵詞呢&#xff1f;下面就隨小編一起來解決這個問題吧。 后臺設置預覽圖&#xff1a; 設置教程&#xff1a; 1、把以下代碼添加至當前主題的 functions.php 文件中&#xff1a; add_action(admi…

【PyTorch】torch.fmod使用截斷正態分布truncated normal distribution初始化神經網絡的權重

這個代碼片段展示了如何用 PyTorch 初始化神經網絡的權重&#xff0c;具體使用的是截斷正態分布&#xff08;truncated normal distribution&#xff09;。截斷正態分布意味著生成的值會在一定范圍內截斷&#xff0c;以防止出現極端值。這里使用 torch.fmod 作為一種變通方法實…

配置linux net.ipv4.ip_forward數據包轉發

前言 出于系統安全考慮&#xff0c;在默認情況下&#xff0c;Linux系統是禁止數據包轉發的。數據包轉發指的是當主機擁有多個網卡時&#xff0c;通過一個網卡接收到的數據包&#xff0c;根據目的IP地址來轉發數據包到其他網卡。這個功能通常用于路由器。 如果在Linux系統中需要…

CVPR 2024最佳論文分享:通過解釋方法比較Transformers和CNNs的決策機制

CVPR&#xff08;Conference on Computer Vision and Pattern Recognition&#xff09;是計算機視覺領域最有影響力的會議之一&#xff0c;主要方向包括圖像和視頻處理、目標檢測與識別、三維視覺等。近期&#xff0c;CVPR 2024 公布了最佳論文。共有10篇論文獲獎&#xff0c;其…

計算組的妙用!!頁面權限控制

需求描述&#xff1a; 某些特殊的場景下&#xff0c;針對某頁看板&#xff0c;需要進行數據權限卡控&#xff0c;但是又不能對全部的數據進行RLS處理&#xff0c;這種情況下可以利用計算組來解決這個需求。 實際場景 事實表包含產品維度和銷售維度 兩個維度屬于同一公司下面的…

限幅濾波法

限幅濾波法 限幅濾波法:根據經驗判斷,確定兩次采樣允許的最大偏差值(設為A),每次檢測到新值時判斷:如果本次值與上次值之差<=A,則本次值有效,如果本次值與上次值之差>A,則本次值無效,放棄本次值,用上次值代替本次值。 優點: 能有效克服因偶然因素引起的脈沖…

【Python】已解決:FileNotFoundError: [Errno 2] No such file or directory: ‘./1.xml’

文章目錄 一、分析問題背景二、可能出錯的原因三、錯誤代碼示例四、正確代碼示例五、注意事項 已解決&#xff1a;FileNotFoundError: [Errno 2] No such file or directory: ‘./1.xml’ 一、分析問題背景 在Python編程中&#xff0c;FileNotFoundError是一個常見的異常&…

ChatGPT對話:Python程序自動模擬操作網頁,無法彈出下拉列表框

【編者按】需要編寫Python程序自動模擬操作網頁。編者有編程經驗&#xff0c;但沒有前端編程經驗&#xff0c;完全不知道如何編寫這種程序。通過與ChatGPT討論&#xff0c;1天完成了任務。因為沒有這類程序的編程經驗&#xff0c;需要邊學習&#xff0c;邊編程&#xff0c;遇到…

貝爾曼方程(Bellman Equation)

貝爾曼方程(Bellman Equation) 貝爾曼方程(Bellman Equation)是動態規劃和強化學習中的核心概念,用于描述最優決策問題中的價值函數的遞歸關系。它為狀態值函數和動作值函數提供了一個重要的遞推公式,幫助我們計算每個狀態或狀態-動作對的預期回報。 貝爾曼方程的原理 …

Python 自動化測試必會技能板塊—unittest框架

說到 Python 的單元測試框架&#xff0c;想必接觸過 Python 的朋友腦袋里第一個想到的就是 unittest。 的確&#xff0c;作為 Python 的標準庫&#xff0c;它很優秀&#xff0c;并被廣泛應用于各個項目。但其實在 Python 眾多項目中&#xff0c;主流的單元測試框架遠不止這一個…

西門子PLC1200--與電腦S7通訊

硬件構成 PLC為西門子1211DCDCDC 電腦上位機用PYTHON編寫 二者通訊用網線&#xff0c;通訊協議用S7 PLC上的數據 PLC上的數據是2個uint&#xff0c;在DB1&#xff0c;地址偏移分別是0和2 需要注意的是DB塊要關閉優化的塊訪問&#xff0c;否則是沒有偏移地址的 PLC中的數據內…