Async Await Not working when using in an endpoint to fetch result from SQL database

Question:

I am new to async await and trying to use it for getting response from a SQL db query method defined at an end point

@router.get('/queryDAS')
async def fetch_das_db():
response = await DASDBData().get_all()
logger.info("---ASYNCRONOUS----")
return (json.dumps(response))

but all I get is this error :
response = await DASDBData().get_all()
TypeError: object list can’t be used in ‘await’ expression

def get_all(self):
    """Get all new data.
    @returns:
        Return list of dictionaries with team information.
    """
  
    result=[]
    statement = """SELECT *
                FROM CAE_APPR_ITEM_RESPONSE WHERE ROWNUM <= 500
                """
    logger.debug(statement)
    cur = self.connection.create_connection().cursor()
    cur.execute(statement)
    for row in cur:
        print(row)
        result.append(row)
    #return (200,result)
    return result

I thought that the message "—ASYNCHRONOUS—" would be printed first as the get_all method would go inside the event_loop but it didnt get printed as well

Asked By: etotientz

||

Answers:

TL;DR

@router.get('/queryDAS')
async def fetch_das_db():
    response = DASDBData().get_all()
    logger.info("---ASYNCRONOUS----")
    return (json.dumps(await response))

Starting from the comments, I really suggest you to read first how async await works. Here is what I believe is a good tutorial about async await.

After you’ve read the tutorial/explanation, you will understand that response = await DASDBData().get_all() will wait for the result of get_all() before going on…behaving like the traditional synchronous code.

Now, if you remove the await keyword, your print statement will run before the method has finished, but you’ll also get a warning about your coroutine not being awaited. This is similar to starting a project, but never ending it. The response variable will thus hold the coroutine, some sort of future result, which is not there yet.

With this in mind, you can then return the result while awaiting it, modifying the last return statement into return (json.dumps(await response)). This will wait for the future result and dump it as string before returning it.

If you need to use the result for some other things, you can import asyncio and then use response = await asyncio.gather(response) to get your response value. This will simply wait for the running coroutine and return the resulting value (i.e. execution is blocked until the function returns something). You can then do whatever you want with the result.

One side note:

FastAPI automatically converts the return value to JSON. Unless you are using a special formatting, I advice to simply return await response (the await may or may not be needed, based on which approach you use).

Answered By: lsabi
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.