Reputation: 93
I'm using Python 3.6.8 and the following packages:
azure-common 1.1.25
azure-core 1.3.0
azure-identity 1.3.0
azure-nspkg 3.0.2
azure-storage-blob 12.3.0
The following line in my code:
await blobClient.upload_blob(data, overwrite=True)
Gives me a stack trace with the message:
TypeError: object AccessToken can't be used in 'await' expression
If I take off the 'await' the code works fine, though it never surrenders control to other tasks, but it does upload the blobs perfectly. I'm using the asynchronous upload_blob() function. I can't understand why I'm getting this error, any ideas?
Here's the code minus some variable assignments:
from azure.identity import ClientSecretCredential
from azure.storage.blob.aio import BlobClient
import asyncio
import os
async def task(name, work_queue):
"""
"""
while not work_queue.empty():
f = await work_queue.get()
blobClient = BlobClient(
"https://{}.blob.core.windows.net".format(accountName),
credential = creds,
container_name = container,
blob_name = (f.replace(sourceDirPrefix, '')),
)
# Upload content to blob
with open(f, "rb") as data:
await blobClient.upload_blob(data, overwrite=True)
def main():
"""
This is the main entry point for the program
"""
# Create the queue of work
work_queue = asyncio.Queue()
# Put some work in the queue
for (path, dirs, files) in os.walk(sourceDir):
for f in files:
work_queue.put_nowait(os.path.join(path, f))
# Run the tasks
loop = asyncio.get_event_loop()
loop.run_until_complete(
asyncio.gather(
task("1", work_queue),
task("2", work_queue),
task("3", work_queue),
)
)
loop.close()
Stack Trace:
Traceback (most recent call last):
File "test04.py", line 77, in <module>
main()
File "test04.py", line 70, in main
task("3", work_queue),
File "/usr/lib64/python3.6/asyncio/base_events.py", line 484, in run_until_complete
return future.result()
File "test04.py", line 44, in task
await blobClient.upload_blob(data, overwrite=True, asyncio=True)
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/core/tracing/decorator_async.py", line 70, in wrapper_use_tracer
return await func(*args, **kwargs)
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/storage/blob/aio/_blob_client_async.py", line 256, in upload_blob
return await upload_block_blob(**options)
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/storage/blob/aio/_upload_helpers.py", line 79, in upload_block_blob
**kwargs)
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/storage/blob/_generated/aio/operations_async/_block_blob_operations_async.py", line 207, in upload
pipeline_response = await self._client._pipeline.run(request, stream=False, **kwargs)
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/core/pipeline/_base_async.py", line 213, in run
return await first_node.send(pipeline_request) # type: ignore
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/core/pipeline/_base_async.py", line 91, in send
response = await self.next.send(request) # type: ignore
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/core/pipeline/_base_async.py", line 91, in send
response = await self.next.send(request) # type: ignore
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/core/pipeline/_base_async.py", line 91, in send
response = await self.next.send(request) # type: ignore
[Previous line repeated 3 more times]
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/core/pipeline/_base_async.py", line 89, in send
await _await_result(self._policy.on_request, request)
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/core/pipeline/_base_async.py", line 62, in _await_result
return await result # type: ignore
File "/work/python/venv_sm_36/lib/python3.6/site-packages/azure/core/pipeline/policies/_authentication_async.py", line 37, in on_request
self._token = await self._credential.get_token(*self._scopes) # type: ignore
TypeError: object AccessToken can't be used in 'await' expression
Upvotes: 2
Views: 2817
Reputation: 136
The problem is that you are using the idenity class calling the ayncio version fo BlobClient. You have to use the async version of the idenity class.
So you have to change from this:
from azure.identity import ClientSecretCredential
To this:
from azure.identity.aio import ClientSecretCredential
Upvotes: 10
Reputation: 29985
In async def task(name, work_queue)
method -> after this line of code blobClient = BlobClient(xxx)
, you should use the code below:
async with blobClient:
with open(f, "rb") as data:
await blobClient.upload_blob(data, overwrite=True)
The completed method:
async def task(name, work_queue):
"""
"""
while not work_queue.empty():
f = await work_queue.get()
blobClient = BlobClient(
"https://{}.blob.core.windows.net".format(accountName),
credential = creds,
container_name = container,
blob_name = (f.replace(sourceDirPrefix, '')),
)
async with blobClient:
with open(f, "rb") as data:
await blobClient.upload_blob(data, overwrite=True)
Upvotes: 2