I'm trying to develop a Python API with FastAPI, and I have to download a series of images from several URLs, in a foor loop.
The problem is that I have to retrieve the images, and I can't do it as it is an async operation inside a normal for loop.
Here is my code:
@app.post("/v1/img_color")
async def img_color(request: Request):
body = await request.json()
images = []
for img in body['images']:
img_id = img['id']
img_url = img['url']
r = requests.get(img_url)
content = await r.content
dw_image = Image.open(BytesIO(content))
images.append(dw_image)
return images
But it gives me the following error:
TypeError: object bytes can't be used in 'await' expression
How can I solve this? I've searched about this issue, and found some solutions regarding asyncio but I can't manage to make them work.
Update:
Following the suggestion of deleting the await code from await r.content, I've reached to another error, which says the following:
TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have dict attribute')
I don't quite understand this, as I can retrieve perfectly the url from the JSON body of the original POST request...
Traceback
Traceback (most recent call last):
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 388, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
return await self.app(scope, receive, send)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\fastapi\applications.py", line 190, in __call__
await super().__call__(scope, receive, send)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\starlette\applications.py", line 111, in __call__
await self.middleware_stack(scope, receive, send)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
raise exc from None
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
await self.app(scope, receive, _send)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\starlette\exceptions.py", line 82, in __call__
raise exc from None
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\starlette\exceptions.py", line 71, in __call__
await self.app(scope, receive, sender)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\starlette\routing.py", line 566, in __call__
await route.handle(scope, receive, send)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\starlette\routing.py", line 227, in handle
await self.app(scope, receive, send)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\starlette\routing.py", line 41, in app
response = await func(request)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\fastapi\routing.py", line 196, in app
response_data = await serialize_response(
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\fastapi\routing.py", line 124, in serialize_response
return jsonable_encoder(response_content)
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\fastapi\encoders.py", line 102, in jsonable_encoder
jsonable_encoder(
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\fastapi\encoders.py", line 140, in jsonable_encoder
return jsonable_encoder(
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\fastapi\encoders.py", line 88, in jsonable_encoder
encoded_value = jsonable_encoder(
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\fastapi\encoders.py", line 88, in jsonable_encoder
encoded_value = jsonable_encoder(
File "d:\users\kendo\documents\git\empathy\kala_api\env\lib\site-packages\fastapi\encoders.py", line 139, in jsonable_encoder
raise ValueError(errors)
ValueError: [TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have __dict__ attribute')]
requests.get()is synchronous. There is nothing toawait. When the call is done, the content bytes are completely available. Remove theawait.awaitcode, but now it gives me a new error (see the update), any idea? Thanks in advance!return images, which is a list ofImageobjects. I imagine your framework is configured to try to convert this to JSON, and it seems to try to turn your[Image1, Image2]into an object{"key1": "value1", "key2": "value2"}. That can't work because there aren't any keys in there. You can try toreturn enumerate(images)to see if the error goes away. You'll need to figure out what return output you want from your endpoint, and what you need to return from your handler function to get it.