AttributeError: module 'asyncio' has no attribute 'create_task'

Benyamin Jafari picture Benyamin Jafari · Nov 11, 2018 · Viewed 12.1k times · Source

I'm trying to asyncio.create_task() but I'm dealing with this error:

Here's an example:

import asyncio
import time

async def async_say(delay, msg):
    await asyncio.sleep(delay)
    print(msg)

async def main():
    task1 = asyncio.create_task(async_say(4, 'hello'))
    task2 = asyncio.create_task(async_say(6, 'world'))

    print(f"started at {time.strftime('%X')}")
    await task1
    await task2
    print(f"finished at {time.strftime('%X')}")

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Out:

AttributeError: module 'asyncio' has no attribute 'create_task'

So I tried with the following code snippet (.ensure_future()) instead, without any problem:

async def main():
    task1 = asyncio.ensure_future(async_say(4, 'hello'))
    task2 = asyncio.ensure_future(async_say(6, 'world'))

    print(f"started at {time.strftime('%X')}")
    await task1
    await task2
    print(f"finished at {time.strftime('%X')}")

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Out:

started at 13:19:44
hello
world
finished at 13:19:50

What's wrong?


[NOTE]:

  • Python 3.6
  • Ubuntu 16.04

[UPDATE]:

With borrowing from @user4815162342 Answer, my problem solved:

async def main():
    loop = asyncio.get_event_loop()
    task1 = loop.create_task(async_say(4, 'hello'))
    task2 = loop.create_task(async_say(6, 'world'))

    print(f"started at {time.strftime('%X')}")
    await task1
    await task2
    print(f"finished at {time.strftime('%X')}")

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Answer

user4815162342 picture user4815162342 · Nov 11, 2018

The create_task top-level function was added in Python 3.7, and you are using Python 3.6. Prior to 3.7, create_task was only available as a method on the event loop, so you can invoke it like that:

async def main():
    loop = asyncio.get_event_loop()
    task1 = loop.create_task(async_say(4, 'hello'))
    task2 = loop.create_task(async_say(6, 'world'))
    # ...
    await task1
    await task2

That works in both 3.6 and 3.7, as well as in earlier versions. asyncio.ensure_future will work as well, but when you know you're dealing with a coroutine, create_task is more explicit and is the preferred option.