最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python異步并發(fā)控制asyncio.gather 與 Semaphore 協(xié)同設(shè)計(jì)解析

 更新時(shí)間:2026年04月05日 09:52:32   作者:喝茶與編碼  
本文詳細(xì)解析了在Python異步編程中使用asyncio.gather與asyncio.Semaphore進(jìn)行并發(fā)控制的重要性,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、文檔概述

在 Python 異步編程(asyncio)體系中,asyncio.gather(*tasks) 是實(shí)現(xiàn)多任務(wù)并發(fā)的核心手段,但僅依賴該方法無法管控并發(fā)規(guī)模,極易引發(fā)資源耗盡、服務(wù)限流等生產(chǎn)級(jí)問題。本文將從核心概念、風(fēng)險(xiǎn)場景、協(xié)同邏輯三個(gè)維度,系統(tǒng)解析為何必須結(jié)合 asyncio.Semaphore(信號(hào)量)進(jìn)行并發(fā)控制,并給出通用化的實(shí)現(xiàn)范式與最佳實(shí)踐,適配各類異步業(yè)務(wù)場景。

二、核心概念辨析

2.1 asyncio.gather:異步任務(wù)的“并發(fā)啟動(dòng)器”

asyncio.gather(*tasks) 是 asyncio 框架中批量執(zhí)行異步協(xié)程的核心 API,其核心能力為:

  • 一次性啟動(dòng)所有傳入的協(xié)程任務(wù),基于事件循環(huán)實(shí)現(xiàn)非阻塞的并發(fā)調(diào)度;
  • 等待所有任務(wù)執(zhí)行完畢后,按任務(wù)傳入順序返回執(zhí)行結(jié)果;
  • 支持通過 return_exceptions=True 配置,避免單個(gè)任務(wù)異常導(dǎo)致整體任務(wù)終止。

核心局限:該方法僅負(fù)責(zé)“觸發(fā)并發(fā)”,但不限制同時(shí)處于運(yùn)行狀態(tài)的任務(wù)數(shù)量。若直接對(duì)大量任務(wù)調(diào)用 gather,所有任務(wù)會(huì)同時(shí)進(jìn)入調(diào)度隊(duì)列,引發(fā)資源過載。

2.2 asyncio.Semaphore:并發(fā)規(guī)模的“流量調(diào)節(jié)器”

asyncio.Semaphore 是 asyncio 提供的輕量級(jí)并發(fā)控制組件,本質(zhì)是“計(jì)數(shù)器 + 等待隊(duì)列”的組合:

  • 初始化時(shí)指定并發(fā)上限 N(如 sem = asyncio.Semaphore(10) 表示最多允許10個(gè)任務(wù)同時(shí)執(zhí)行);
  • 通過 async with sem 進(jìn)入上下文管理:
    • 若當(dāng)前運(yùn)行任務(wù)數(shù) < N:計(jì)數(shù)器減1,任務(wù)直接執(zhí)行;
    • 若當(dāng)前運(yùn)行任務(wù)數(shù) = N:任務(wù)進(jìn)入等待隊(duì)列,直至已有任務(wù)執(zhí)行完成并釋放信號(hào)量(計(jì)數(shù)器加1);
  • 最終實(shí)現(xiàn)“始終只有 N 個(gè)任務(wù)并行,剩余任務(wù)排隊(duì)執(zhí)行”的效果,從根源上控制并發(fā)規(guī)模。

三、為什么必須搭配使用?

3.1 無 Semaphore 的并發(fā)風(fēng)險(xiǎn)(通用場景示例)

批量調(diào)用第三方HTTP接口為例(通用化場景,適配接口調(diào)用、數(shù)據(jù)查詢等絕大多數(shù)異步業(yè)務(wù)):

import asyncio
import aiohttp

# 通用異步任務(wù):調(diào)用第三方接口獲取數(shù)據(jù)
async def fetch_data(api_path: str):
    async with aiohttp.ClientSession() as session:
        # 模擬調(diào)用各類第三方接口(如支付、短信、數(shù)據(jù)查詢)
        resp = await session.get(f"https://api.example.com{api_path}")
        return await resp.json()

async def batch_fetch(api_paths: list):
    # 直接創(chuàng)建所有任務(wù)并并發(fā)執(zhí)行
    tasks = [fetch_data(path) for path in api_paths]
    # 無并發(fā)限制:所有任務(wù)同時(shí)發(fā)起請(qǐng)求
    results = await asyncio.gather(*tasks)
    return results

# 執(zhí)行:一次性發(fā)起500個(gè)HTTP請(qǐng)求
if __name__ == "__main__":
    api_list = [f"/data/{i}" for i in range(500)]
    asyncio.run(batch_fetch(api_list))

上述代碼在生產(chǎn)環(huán)境中會(huì)引發(fā)三類核心問題:

  1. 服務(wù)端限流/熔斷:瞬間500個(gè)請(qǐng)求超出第三方接口的QPS限制,導(dǎo)致請(qǐng)求被拒絕、接口熔斷甚至IP被拉黑;
  2. 客戶端資源耗盡:大量并發(fā)協(xié)程占用過多的網(wǎng)絡(luò)連接、CPU和內(nèi)存資源,引發(fā)程序響應(yīng)超時(shí)、系統(tǒng)卡頓;
  3. 任務(wù)執(zhí)行不穩(wěn)定:前期請(qǐng)求集中積壓,后期因接口限流導(dǎo)致大量任務(wù)超時(shí)失敗,整體執(zhí)行效率反而低于可控并發(fā)。

3.2 搭配 Semaphore 的核心優(yōu)勢(shì)

在上述通用場景中加入 Semaphore 控制并發(fā)上限(如10),實(shí)現(xiàn)“可控并發(fā)”:

import asyncio
import aiohttp

async def fetch_data(api_path: str, sem: asyncio.Semaphore):
    # 信號(hào)量控制:同一時(shí)間僅10個(gè)任務(wù)執(zhí)行該邏輯
    async with sem:
        async with aiohttp.ClientSession() as session:
            resp = await session.get(f"https://api.example.com{api_path}")
            return await resp.json()

async def batch_fetch(api_paths: list):
    # 初始化信號(hào)量,設(shè)置并發(fā)上限10
    sem = asyncio.Semaphore(10)
    # 任務(wù)創(chuàng)建時(shí)傳入信號(hào)量
    tasks = [fetch_data(path, sem) for path in api_paths]
    results = await asyncio.gather(*tasks)
    return results

# 執(zhí)行:始終保持10個(gè)請(qǐng)求并行,剩余任務(wù)排隊(duì)
if __name__ == "__main__":
    api_list = [f"/data/{i}" for i in range(500)]
    asyncio.run(batch_fetch(api_list))

優(yōu)化后的核心收益:

  1. 資源占用平穩(wěn):CPU、內(nèi)存、網(wǎng)絡(luò)連接數(shù)始終處于可控范圍,避免系統(tǒng)過載;
  2. 符合服務(wù)規(guī)則:按接口QPS限制勻速發(fā)起請(qǐng)求,杜絕限流/拉黑風(fēng)險(xiǎn);
  3. 執(zhí)行效率可控:任務(wù)按批次執(zhí)行,減少超時(shí)和失敗概率,整體耗時(shí)可預(yù)期。

四、通用化協(xié)同設(shè)計(jì)實(shí)現(xiàn)范式

4.1 標(biāo)準(zhǔn)模板(適配所有異步批量任務(wù))

以下模板可直接復(fù)用至接口調(diào)用、文件IO、數(shù)據(jù)庫查詢等各類異步場景:

import asyncio
import logging
from typing import List, Any, Dict

# 初始化通用日志器
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class AsyncBatchProcessor:
    """通用異步批量處理器,結(jié)合gather與Semaphore實(shí)現(xiàn)可控并發(fā)"""
    def __init__(self, concurrency_limit: int = 10):
        """
        初始化處理器
        :param concurrency_limit: 并發(fā)上限,默認(rèn)10(可根據(jù)業(yè)務(wù)調(diào)整)
        """
        self.concurrency_limit = concurrency_limit
        self.semaphore = asyncio.Semaphore(concurrency_limit)

    async def _process_single(self, item: Any) -> Dict[str, Any]:
        """
        處理單個(gè)任務(wù)(核心業(yè)務(wù)邏輯,可按需重寫)
        :param item: 單個(gè)任務(wù)參數(shù)(如接口路徑、文件路徑、數(shù)據(jù)庫ID等)
        :return: 任務(wù)執(zhí)行結(jié)果
        """
        async with self.semaphore:  # 信號(hào)量控制并發(fā)規(guī)模
            try:
                # 替換為實(shí)際業(yè)務(wù)邏輯(如接口調(diào)用、文件讀寫、數(shù)據(jù)計(jì)算)
                await asyncio.sleep(0.1)  # 模擬異步操作
                logger.info(f"任務(wù){(diào)item}執(zhí)行完成")
                return {"status": "success", "item": item, "result": "ok"}
            except Exception as e:
                logger.error(f"任務(wù){(diào)item}執(zhí)行失敗: {str(e)}")
                return {"status": "failed", "item": item, "error": str(e)}

    async def batch_process(self, items: List[Any]) -> List[Dict[str, Any]]:
        """
        批量處理任務(wù)
        :param items: 任務(wù)列表(通用化參數(shù),適配任意類型)
        :return: 所有任務(wù)的執(zhí)行結(jié)果
        """
        # 創(chuàng)建所有異步任務(wù)
        tasks = [self._process_single(item) for item in items]
        # 并發(fā)執(zhí)行(由Semaphore控制并發(fā)上限)
        results = await asyncio.gather(*tasks, return_exceptions=False)
        return results

# 通用調(diào)用示例
async def main():
    # 初始化處理器,設(shè)置并發(fā)上限5
    processor = AsyncBatchProcessor(concurrency_limit=5)
    # 模擬任意類型的任務(wù)列表(接口路徑、ID、文件路徑等)
    task_list = [f"task_{i}" for i in range(20)]
    # 批量執(zhí)行任務(wù)
    results = await processor.batch_process(task_list)
    # 統(tǒng)計(jì)執(zhí)行結(jié)果
    success_count = len([r for r in results if r["status"] == "success"])
    failed_count = len([r for r in results if r["status"] == "failed"])
    logger.info(f"批量處理完成:成功{success_count}個(gè),失敗{failed_count}個(gè)")

if __name__ == "__main__":
    asyncio.run(main())

4.2 關(guān)鍵設(shè)計(jì)要點(diǎn)

  1. Semaphore 作用域:async with self.semaphore 需包裹核心異步操作(如接口調(diào)用、IO讀寫),而非整個(gè)任務(wù)函數(shù),保證控制粒度精準(zhǔn);
  2. 異常隔離:單個(gè)任務(wù)的異常需在 _process_single 內(nèi)捕獲,避免影響其他任務(wù)執(zhí)行;
  3. 參數(shù)通用化:任務(wù)參數(shù)設(shè)計(jì)為任意類型(Any),適配接口路徑、數(shù)據(jù)庫ID、文件路徑等各類業(yè)務(wù)場景;
  4. 結(jié)果可追溯:返回每個(gè)任務(wù)的執(zhí)行狀態(tài)(成功/失?。?,便于問題排查和結(jié)果統(tǒng)計(jì)。

五、最佳實(shí)踐與場景適配

5.1 并發(fā)上限設(shè)置原則

業(yè)務(wù)場景并發(fā)上限建議值核心依據(jù)
第三方接口調(diào)用參考接口QPS限制(如QPS=20則設(shè)20)避免觸發(fā)接口限流/熔斷
本地文件/數(shù)據(jù)庫IOCPU核心數(shù) × 2(如4核設(shè)8)平衡IO等待與CPU利用率
高耗時(shí)計(jì)算型任務(wù)CPU核心數(shù)(如8核設(shè)8)避免CPU資源競爭

5.2 生產(chǎn)級(jí)優(yōu)化建議

  1. 動(dòng)態(tài)調(diào)優(yōu):從低上限開始(如10),逐步增加至“耗時(shí)不再降低”的拐點(diǎn),避免過度并發(fā);
  2. 資源復(fù)用:將HTTP Session、數(shù)據(jù)庫連接池等資源初始化在信號(hào)量作用域外,減少資源創(chuàng)建銷毀開銷;
  3. 監(jiān)控埋點(diǎn):增加任務(wù)執(zhí)行時(shí)長、并發(fā)數(shù)、成功率等指標(biāo)監(jiān)控,便于線上問題定位;
  4. 優(yōu)雅退出:結(jié)合 asyncio.Event 實(shí)現(xiàn)任務(wù)的優(yōu)雅中斷,避免強(qiáng)制終止導(dǎo)致的數(shù)據(jù)丟失。

六、總結(jié)

  1. asyncio.gather 是異步任務(wù)的“并發(fā)啟動(dòng)器”,負(fù)責(zé)批量啟動(dòng)和等待任務(wù),但無并發(fā)規(guī)模限制;
  2. asyncio.Semaphore 是并發(fā)規(guī)模的“流量調(diào)節(jié)器”,通過設(shè)置上限保證系統(tǒng)資源穩(wěn)定,避免過載;
  3. 二者搭配是異步并發(fā)編程的“標(biāo)準(zhǔn)范式”:gather 解決“高效并發(fā)”問題,Semaphore 解決“可控并發(fā)”問題,缺一不可。

核心原則:異步并發(fā)的價(jià)值是“高效且穩(wěn)定”,gather 實(shí)現(xiàn)高效,Semaphore 保障穩(wěn)定,二者協(xié)同才能滿足生產(chǎn)環(huán)境的核心訴求。

到此這篇關(guān)于Python異步并發(fā)控制asyncio.gather 與 Semaphore 協(xié)同設(shè)計(jì)解析的文章就介紹到這了,更多相關(guān)Python異步并發(fā)asyncio.gather 與 Semaphore 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python讀取ini配置文件傳參的簡單示例

    Python讀取ini配置文件傳參的簡單示例

    這篇文章主要給大家介紹了關(guān)于Python讀取ini配置文件傳參的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Python常用模塊之datetime模塊詳解

    Python常用模塊之datetime模塊詳解

    這篇文章主要介紹了Python常用模塊之datetime模塊詳解,datetime是Python處理日期和時(shí)間的標(biāo)準(zhǔn)庫,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • Flask處理POST請(qǐng)求的教程指南

    Flask處理POST請(qǐng)求的教程指南

    Flask處理POST請(qǐng)求的過程是一個(gè)相對(duì)直接且靈活的過程,它允許開發(fā)者根據(jù)需求接收、處理并響應(yīng)客戶端發(fā)送的數(shù)據(jù),以下是對(duì)Flask如何處理POST請(qǐng)求的詳細(xì)簡述,需要的朋友可以參考下
    2024-10-10
  • python Gabor濾波器講解

    python Gabor濾波器講解

    這篇文章主要介紹了python Gabor濾波器講解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Python中psutil模塊使用匯總

    Python中psutil模塊使用匯總

    psutil模塊是一個(gè)跨平臺(tái)庫,用于檢索Python中運(yùn)行進(jìn)程和系統(tǒng)利用率(CPU、內(nèi)存、磁盤、網(wǎng)絡(luò)、傳感器)的信息。它主要用于系統(tǒng)監(jiān)視、分析和限制進(jìn)程資源以及管理正在運(yùn)行的進(jìn)程,本文給大家介紹Python中psutil模塊使用匯總,感興趣的朋友一起看看吧
    2021-12-12
  • Python BautifulSoup 節(jié)點(diǎn)信息

    Python BautifulSoup 節(jié)點(diǎn)信息

    這篇文章主要介紹了Python BautifulSoup 節(jié)點(diǎn)信息,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • python pdfkit 中文亂碼問題的解決方案

    python pdfkit 中文亂碼問題的解決方案

    這篇文章主要介紹了python pdfkit 中文亂碼問題的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Python 實(shí)現(xiàn)大整數(shù)乘法算法的示例代碼

    Python 實(shí)現(xiàn)大整數(shù)乘法算法的示例代碼

    這篇文章主要介紹了Python 實(shí)現(xiàn)大整數(shù)乘法算法的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Python文件去除注釋的方法

    Python文件去除注釋的方法

    這篇文章主要介紹了Python文件去除注釋的方法,涉及Python正則表達(dá)式及文件操作的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • Python Opencv實(shí)戰(zhàn)之文字檢測OCR

    Python Opencv實(shí)戰(zhàn)之文字檢測OCR

    這篇文章主要為大家詳細(xì)介紹了如何利用Python Opencv實(shí)現(xiàn)文字檢測OCR功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下
    2022-08-08

最新評(píng)論

江川县| 清原| 金平| 长寿区| 犍为县| 旬阳县| 平凉市| 龙泉市| 锡林郭勒盟| 东乌珠穆沁旗| 营口市| 华阴市| 兴安盟| 万安县| 江门市| 石门县| 壤塘县| 宜良县| 湘阴县| 鲁山县| 吴江市| 连南| 连山| 锡林浩特市| 外汇| 嘉禾县| 行唐县| 无为县| 和政县| 湖口县| 潼关县| 青州市| 玛曲县| 北京市| 嘉祥县| 玉田县| 崇阳县| 文昌市| 衡水市| 南乐县| 时尚|