57
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import time

async def foo():
  await time.sleep(1)

foo()

I couldn't make this dead simple example to run:

RuntimeWarning: coroutine 'foo' was never awaited foo()
1
  • Time.sleep is NOT a coroutine so you can't await this even if you properly run the event loop. Moreover if you use blocking code in the event loop you make it synchronous again. There is no point to do this. Commented Aug 30, 2019 at 17:38

2 Answers 2

80

Running coroutines requires an event loop. Use the asyncio() library to create one:

import asyncio

# Python 3.7+
asyncio.run(foo())

or

# Python 3.6 and older
loop = asyncio.get_event_loop()
loop.run_until_complete(foo())

Also see the Tasks and Coroutines chapter of the asyncio documentation. If you already have a loop running, you'd want to run additional coroutines concurrently by creating a task (asyncio.create_task(...) in Python 3.7+, asyncio.ensure_future(...) in older versions).

Note however that time.sleep() is not an awaitable object. It returns None so you get an exception after 1 second:

>>> asyncio.run(foo())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/.../lib/python3.7/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/.../lib/python3.7/asyncio/base_events.py", line 573, in run_until_complete
    return future.result()
  File "<stdin>", line 2, in foo
TypeError: object NoneType can't be used in 'await' expression

In this case you should use the asyncio.sleep() coroutine instead:

async def foo():
    await asyncio.sleep(1)

which is cooperates with the loop to enable other tasks to run. For blocking code from third-party libraries that do not have asyncio equivalents, you could run that code in an executor pool. See Running Blocking Code in the asyncio development guide.

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

2 Comments

If foo() is function from one library, is it possible to encapsulate (without modify the source code) to meet await requirement?
@northtree: You can run blocking code in a threadpool executor to free the asyncio event loop thread though. Just be careful with blocking threads that have no way of cancelling them.
3

If you already have a loop running (with some other tasks), you can add new tasks with:

asyncio.ensure_future(foo())

otherwise you might get

The event loop is already running

error.

Comments

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.