2

I am trying to call a REST API async using asyncio but i keep getting the error "coroutine was never awaited" which i understand. But i want this behavior, i want my function to end just by posting and not waiting for the result. Here is my code

async def callCoroutine:
    #call a REST API 

def lambda_handler(event, context):   
    loop = asyncio.get_event_loop()
    task = loop.create_task(callCoroutine(data))
    return

Can someone help?

1
  • 2
    Are you running the loop somewhere? Commented Aug 3, 2018 at 14:48

3 Answers 3

1

If you just need to call the API, disregarding the result, you can use an Executor in another thread, which will not block the main thread.

To run in an Executor, use AbstractEventLoop.run_in_executor() with an Executor from concurrent.futures.

Sign up to request clarification or add additional context in comments.

1 Comment

@Bhargav The ThreadPoolExecutor example is easily adapted for your use case
1

For the current example, you need to have running loop somewhere (e.g. if you have some web-server or worker - loop.run_forever())

Fixed code example with running loop

import asyncio


async def callCoroutine(data):
    print('This is data: %s' % data)


def lambda_handler(event, context):   
    loop = asyncio.get_event_loop()
    task = loop.create_task(callCoroutine(context))
    return

lambda_handler(None, {'a': 1})

loop = asyncio.get_event_loop()
loop.run_forever()

Example with run_in_executor()

import asyncio
import requests


def call_rest_api(data):
    print('Triggered REST API in background')
    response = requests.get(data['url'])
    print('Response: %s' % response)


async def main(loop):
    print('Some operations here...')

    data = {'url': 'http://example.com#some_rest_api'}
    loop.run_in_executor(None, call_rest_api, data)

    print('Continue work of main thread...')


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))

Example with simple await (if you need to call API syncronously)

But it is not necessary to use asyncio if you want to write synchronous code.

import asyncio
import requests


def call_rest_api(data):
    print('Triggered REST API in background')
    response = requests.get(data['url'])
    print('Response: %s' % response)


async def main(loop):
    print('Some operations here...')

    data = {'url': 'http://example.com#some_rest_api'}
    await call_rest_api(data)

    print('Continue work of main thread...')


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main(loop))

Can you provide more verbose example of what you have and what you want to achive?

10 Comments

Thats the issue, if i use loop.run_forever(), that will stall the main thread to wait. Which i dont want to.
You need to schedule all events (including main thread) in the same loop, or if you have something CPU heavy you'll need to use run_in_executor() instead of create_task(). So you'll don't need threads at all. Or the most preferable way is to move all "lambda_handlers" to separate component/process which will be responsible for callbacks only and the main thread will work on something synchronous.
can you give an example using run_in_executor() then?
@Bhargav added.
This exactly has the same problem i was talking about, this piece of code doesn't finish as long as API call is not finished. Which is not what i want, i want the whole code to stop.
|
1

In your case, the main thread is running synchronously. So you need to run the asyncio loop in another thread Using asyncio.run_coroutine_threadsafe.

import asyncio
import threading

# Run asyncio loop in other thread
loop = asyncio.new_event_loop()
threading.Thread(target=loop.run_forever).start()


async def call_coroutine(data):
    # call a REST API 
    return


def lambda_handler(event, context):   
    # Run the coroutine on the loop of other thread
    future = asyncio.run_coroutine_threadsafe(call_coroutine(data), loop)
    # If need to get result: 
    result = future.result()  # This will block the main thread

    do_something_else()
    return

# If need to stop the asyncio loop
loop.call_soon_threadsafe(loop.stop)

3 Comments

This is not what i want, my main thread responsibility is only to call the API and go bust.
If you don't want to use event loop, you shouldn't use asyncio. You can call the api in another thread or process.
@Bhargav I misunderstood you question before😓. Maybe the new answer can help you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.