2

I am trying to use use grequests to make a single HTTP call asynchronously. All goes find until I try to call a function (handle_cars) to handle the response. The problem is that the function is an async function and it I don't know how to await it while passing.

Is this even possible?

I need the function to be async because there is another async function I need to call from it. Another solution would be to be able to call and await the other async function (send_cars) from inside the sync function.

async def handle_cars(res):
    print("GOT IT")
    await send_cars()
async def get_cars():
    req = grequests.get(URL, hooks=dict(response=handle_cars))
    job = grequests.send(req, grequests.Pool(1))

How do I set the response argument to await the function? Or how do I await send_cars if I make handle_cars synchronous?

Thanks

Tiago
  • 347
  • 1
  • 3
  • 12
  • asyncio and g-event are 2 different asynchronous frameworks. Why don't you use something like aiohttp? I'm not sure if the hooks are called from a different greenlet, and if so, I'm not sure how asyncio will handle it without using threadsafe functions. – Bharel Sep 08 '20 at 23:15
  • @Bharel well I tried using aiohttp but just like almost every other alternative everyone, including the documentation seems to only care about sending multiple requests asynchronously. That's not my case. I want to send a single request but keep doing things while i'ts completed (imagine a loop after the request in `get_cars`). When It is completed I want it to do something with the result (like running `handle_cars`). I could not find a way to do that with aiohttp – Tiago Sep 09 '20 at 12:32
  • The way to do that using the asyncio framework is to create a task, (`asyncio.create_task()`) and add a callback for completion using `task.add_done_callback()`. Lemme write the complete answer below – Bharel Sep 09 '20 at 13:59

1 Answers1

1

According to the OP's comments, he wishes to create a request in the background, and call a callback when it finishes.

The way to do so can be implemented using asyncio.create_task() and using task.add_done_callback().

A simpler way however, will work by creating a new coroutine and running it in the background.

Demonstrated using aiohttp, it will work in the following way:

async def main_loop():
    task = asyncio.create_task(handle_cars(URL))
    while True:
        ...

async def handle_cars(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            await send_cars()
Bharel
  • 23,672
  • 5
  • 40
  • 80
  • this does not work. I have tried it and If I have other functions running it will still wait for the request to complete to resume them. I think I will have to go with threads, the only missing part seems to be calling the async function and awaiting it as callback. – Tiago Sep 11 '20 at 02:33
  • @Tiago doesn't make sense. What are your other functions? Are they not async? – Bharel Sep 11 '20 at 12:41