You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Blob异步download_blob调用asyncio.run二次执行失败问题排查

问题原因分析
  • 异步ContainerClient实例在第一次通过async with上下文管理器使用后,会自动关闭内部的HTTP会话(如aiohttp会话),释放相关资源。
  • 第二次调用时,客户端实例已处于关闭状态,内部会话对象变为None,执行download_blob时无法重建连接,因此抛出AttributeError。
  • 另外,asyncio.run每次调用都会创建新事件循环,第一次运行后客户端资源已被清理,无法跨事件循环复用。
解决办法

方案一:每次调用创建新的ContainerClient实例

将客户端创建逻辑放入异步函数内部,确保每次调用使用全新客户端:

from azure.storage.blob.aio import ContainerClient
from azure.identity import DefaultAzureCredential
import asyncio

async def test(container_url, blob_path):
    credentials = DefaultAzureCredential()
    async with ContainerClient.from_container_url(container_url=container_url, credential=credentials) as client_conn:
        stream = await client_conn.download_blob(blob_path)
        data = await stream.readall()
    return data

if __name__ == "__main__":
    my_container_url = "你的容器URL"
    my_path = 'test_path'

    data = asyncio.run(test(my_container_url, my_path))
    data2 = asyncio.run(test(my_container_url, my_path))

方案二:在同一事件循环内执行多次调用

避免多次调用asyncio.run,在单个事件循环中完成所有下载操作:

from azure.storage.blob.aio import ContainerClient
from azure.identity import DefaultAzureCredential
import asyncio

async def download_blob(client, blob_path):
    stream = await client.download_blob(blob_path)
    return await stream.readall()

async def main():
    my_container_url = "你的容器URL"
    my_path = 'test_path'
    credentials = DefaultAzureCredential()
    async with ContainerClient.from_container_url(container_url=my_container_url, credential=credentials) as client:
        data = await download_blob(client, my_path)
        data2 = await download_blob(client, my_path)
    return data, data2

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

方案三:手动管理客户端生命周期(不推荐)

若需复用客户端,需避免async with自动关闭,手动控制生命周期,但要注意跨事件循环复用可能引发资源问题:

from azure.storage.blob.aio import ContainerClient
from azure.identity import DefaultAzureCredential
import asyncio

async def test(conn_client, blob_path):
    stream = await conn_client.download_blob(blob_path)
    data = await stream.readall()
    return data

if __name__ == "__main__":
    my_container_url = "你的容器URL"
    my_path = 'test_path'
    credentials = DefaultAzureCredential()
    my_client = ContainerClient.from_container_url(container_url=my_container_url, credential=credentials)

    try:
        data = asyncio.run(test(my_client, my_path))
        data2 = asyncio.run(test(my_client, my_path))
    finally:
        asyncio.run(my_client.close())
关键说明
  • 异步Azure SDK客户端(如ContainerClient)设计为单次上下文管理器使用或在同一事件循环内复用,不支持跨多次asyncio.run调用复用。
  • asyncio.run每次调用结束会关闭事件循环并清理所有资源,第一次运行后客户端内部状态已失效。

内容的提问来源于stack exchange,提问作者Ziur Olpa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 16:46:11