aio download_blob works once but not twice when run with asyncio.run

158 views Asked by At

The code aio download_blob of the azure blob works once but not twice when run with asyncio.run, this looks like a bug related to iohttp, but could not figure out how to solve it. (Windows)

The code i have is almost a copy from their original example at: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/storage/azure-storage-blob/samples/blob_samples_hello_world_async.py

from azure.storage.blob.aio import ContainerClient
from azure.identity import DefaultAzureCredential
credentials = DefaultAzureCredential()

async def test(conn_client):
    async with conn_client as client_conn:
        stream = await client_conn.download_blob(my_path)
        data = await stream.readall()
    return data

if __name__ == "__main__":
    my_container_name = "Container name"
    my_client = ContainerClient.from_container_url(container_url=my_container_name, credential=credentials)
    my_path = 'test_path'

    data = asyncio.run(test(my_client)) # works and returns the file from blob storage
    data2 = asyncio.run(test(my_client)) # doesn't work

Error Message:

DEBUG - asyncio: Using proactor: IocpProactor
...
    await self.open()
  File "C...\Cache\virtualenvs\transformer-wi-nHELc-py3.11\Lib\site-packages\azure\core\pipeline\transport\_aiohttp.py", line 127, in open
    await self.session.__aenter__()
          ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute '__aenter__'. Did you mean: '__delattr__'?

Process finished with exit code 1

Any idea or work around?

1

There are 1 answers

4
Venkatesan On

aio download_blob works once but not twice when run with asyncio.run Any idea or workaround?

The error tells that in the Azure SDK code is trying to enter a session that is None. This can happen when the aiohttp session is being closed before the second download operation.

You can pass the destination file path in the list and call the function with that list.

Here is my code to download Blob twice from Blob Storage to the local environment.

Code:

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

async def download_blob(conn_client,path,l):
    for i in l:
        with open(i, "wb") as my_blob:
            stream = await conn_client.download_blob(path)
            data = await stream.readall()
            my_blob.write(data)
            my_blob.close()

async def main():
    my_container_url = "https://xxxxx.blob.core.windows.net/test"
    credentials = DefaultAzureCredential()
    my_client = ContainerClient.from_container_url(container_url=my_container_url, credential=credentials)
    my_path = 'your blob name'
    l = [r"C:\Users\xx\xxxx\samp.csv",r"C:\Users\xxxxxx\samp1.csv"]
    await download_blob(my_client, my_path,l)
    await my_client.close()
    
if __name__ == "__main__":
    asyncio.run(main())
 

The above code executed and downloaded the CSV file twice to my local folder.

Files: enter image description here