How to Get the Current Asyncio Task in Python - Super Fast Python

You can get the current task via asyncio.current_task() function.

In this tutorial, you will discover how to get and use the current asyncio task in Python.

Let’s get started.

What is an Asyncio Task

An asyncio Task is an object that schedules and independently runs an asyncio coroutine.

It provides a handle on a scheduled coroutine that an asyncio program can query and use to interact with the coroutine.

A Task is an object that manages an independently running coroutine.

PEP 3156 – Asynchronous IO Support Rebooted: the “asyncio” Module

An asyncio task is represented via an instance of the asyncio.Task class.

A task is created from a coroutine. It requires a coroutine object, wraps the coroutine, schedules it for execution, and provides ways to interact with it.

A task is executed independently. This means it is scheduled in the asyncio event loop and will execute regardless of what else happens in the coroutine that created it. This is different from executing a coroutine directly, where the caller must wait for it to complete.

Tasks are used to schedule coroutines concurrently. When a coroutine is wrapped into a Task with functions like asyncio.create_task() the coroutine is automatically scheduled to run soon

Coroutines and Tasks

We can create a task using the asyncio.create_task() function.

This function takes a coroutine instance and an optional name for the task and returns an asyncio.Task instance.

Wrap the coro coroutine into a Task and schedule its execution. Return the Task object.

Coroutines and Tasks

For example:

...

# create and schedule a task

task = asyncio.create_task(coro)

You can learn more about asyncio tasks in the tutorial:

Now that we know about asyncio tasks, let’s look at how we might get the current task.

We can get the current task via the asyncio.current_task() function.

This function will return a Task object for the task that is currently running.

For example:

...

# get the current task

task = asyncio.current_task()

This will return a Task object for the currently running task.

This may be:

  • The main coroutine passed to asyncio.run().
  • A task created and scheduled within the asyncio program via asyncio.create_task().

A task may create and run another coroutine (e.g. not wrapped in a task). Getting the current task from within a coroutine will return a Task object for the running task, but not the coroutine that is currently running.

Getting the current task can be helpful if a coroutine or task requires details about itself, such as the task name for logging.

Now that we know how to get the current task, let’s look at some worked examples.

Example of Getting the Current Task in the Main Coroutine

We can explore how to get a Task instance for the main coroutine used to start an asyncio program.

The example below defines a coroutine used as the entry point into the program. It reports a message, then gets the current task and reports its details.

This is an important first example, as it highlights that all coroutines can be accessed as tasks within the asyncio event loop.

The complete example is listed below.

# SuperFastPython.com

# example of getting the current task from the main coroutine

import asyncio

# define a main coroutine

async def main():

    # report a message

    print('main coroutine started')

    # get the current task

    task = asyncio.current_task()

    # report its details

    print(task)

# start the asyncio program

asyncio.run(main())

Running the example first creates the main coroutine and uses it to start the asyncio program.

The main() coroutine runs and first reports a message.

It then retrieves the current task, which is a Task object that represents itself, the currently running coroutine.

It then reports the details of the currently running task.

We can see that the task has the default name for the first task, ‘Task-1‘ and is executing the main() coroutine, the currently running coroutine.

This highlights that we can use the asyncio.current_task() function to access a Task object for the currently running coroutine, that is automatically wrapped in a Task object.

main coroutine started

<Task pending name='Task-1' coro=<main() running at ...> cb=[_run_until_complete_cb() at ...]>

Next, let’s take a look at how we might get a Task object from another coroutine.


Free Python Asyncio Course

Download your FREE Asyncio PDF cheat sheet and get BONUS access to my free 7-day crash course on the Asyncio API.

Discover how to use the Python asyncio module including how to define, create, and run new coroutines and how to use non-blocking I/O.

Learn more
 


Example of Getting the Current Task From Another Coroutine

The asyncio.current_task() function can also be used to retrieve a Task object for the current task from another coroutine that is currently running.

We can explore running a second coroutine in an asyncio program and getting the current Task object from within it.

In this example, the main coroutine is used as the entry point into the program. It is converted into a Task automatically.

The main coroutine creates and runs a second coroutine and this second coroutine retrieves the current task, which refers to the main coroutine, not the currently running coroutine.

The complete example is listed below.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

# SuperFastPython.com

# example of getting the current task from another coroutine

import asyncio

# define another coroutine

async def another_coroutine():

    # report a message

    print('executing the coroutine')

    # get the current task

    task = asyncio.current_task()

    # report its details

    print(task)

# define a main coroutine

async def main():

    # report a message

    print('main coroutine started')

    # wait another coroutine

    await another_coroutine()

    # report a final message

    print('main coroutine done')

# start the asyncio program

asyncio.run(main())

Running the example creates the main() coroutine and uses it as the entry point into the asyncio program.

The main() coroutine reports a message, then creates and runs a second coroutine, then suspends waiting for it to be done.

The second coroutine runs, first reporting a message. It then gets the current Task object for itself and reports its details.

We can see that the asyncio.current_task() returns a Task instance for the main() coroutine that was wrapped in a task when it was used to start the program.

It does not refer to the coroutine that is currently running.

This highlights that the coroutine used as the entry point is turned into a task within the event loop, but arbitrary coroutines executing within a task are not themselves turned into a task and cannot be referenced directly as tasks.

main coroutine started

executing the coroutine

<Task pending name='Task-1' coro=<main() running at ...> cb=[_run_until_complete_cb() at ...]>

main coroutine done

Next, we will look at getting a task object for a new separate task.

Example of Getting the Current Task From Another Task

We can create and schedule a new task and the new task can get a Task object to reference itself.

In this example, we will define a coroutine that we will then wrap in a new Task. The task will get itself and report its details.

The complete example is listed below.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

# SuperFastPython.com

# example of getting the current task from another task

import asyncio

# define another coroutine

async def another_coroutine():

    # report a message

    print('executing the task')

    # get the current task

    task = asyncio.current_task()

    # report its details

    print(task)

# define a main coroutine

async def main():

    # report a message

    print('main coroutine started')

    # create another task

    task = asyncio.create_task(another_coroutine())

    # await the task

    await task

    # report a final message

    print('main coroutine done')

# start the asyncio program

asyncio.run(main())

Running the example creates the main() coroutine and uses it as the entry point into the asyncio program.

The main() coroutine reports a message. It then creates and schedules a task and suspends it until it is done.

The new task runs. It reports a message, then gets a Task object for the currently running task and reports its details.

We can see that a new second task was created and used to execute the second coroutine. It has the name ‘Task-2‘, compared to ‘Task-1‘ for the entry point to the program that we saw in the above example. We can also see that the coroutine executed by the task matches our new second coroutine.

This highlights that we can get a Task object for new tasks that are created and scheduled within our program.

main coroutine started

executing the task

<Task pending name='Task-2' coro=<another_coroutine() running at ...> cb=[Task.task_wakeup()]>

main coroutine done

Next, let’s look at what happens if a task attempts to await itself.


Python Asyncio Jump-Start

Loving The Tutorials?

Why not take the next step? Get the book.

Learn more
 


Example of a Task awaiting Itself

A task cannot await itself.

If we get the current task and then attempt to await it, a RuntimeError will be raised.

We can demonstrate this with a worked example.

# SuperFastPython.com

# example of getting the current task and waiting on itself

import asyncio

# define a main coroutine

async def main():

    # report a message

    print('main coroutine started')

    # get the current task

    task = asyncio.current_task()

    # attempt to wait on itself

    await task

# start the asyncio program

asyncio.run(main())

Running the example creates the main() coroutine and uses it as the entry point into the asyncio program.

The main() coroutine runs, first reporting a message.

It then gets the Task object for the currently running task, which refers to itself.

It then attempts to await this task, which is itself.

This fails with a RuntimeError and a message that a task cannot await itself.

This highlights that a task can interact with itself (introspection), but it cannot await itself.

main coroutine started

Traceback (most recent call last):

  ...

RuntimeError: Task cannot await on itself: <Task pending name='Task-1' coro=<main() running at ...> cb=[_run_until_complete_cb() at ...]>

Next, let’s look at what happens if a task attempts to cancel itself.

Example of a Task Canceling Itself

Once a task gets a reference to itself, it can then query or perform operations on itself.

One operation a task may perform on itself is canceling the task via the cancel() method.

Recall that launching a task will raise a CancelledError exception in the running coroutine wrapped in the task.

You can learn more about canceling tasks in the tutorial:

A task can cancel itself.

If a task calls the cancel() method on itself, it will in turn raise a CancelledError exception in the currently running coroutine.

The example below demonstrates this.

# SuperFastPython.com

# example of getting the current task and canceling itself

import asyncio

# define a main coroutine

async def main():

    # report a message

    print('main coroutine started')

    # get the current task

    task = asyncio.current_task()

    # attempt to cancel the task

    was_canceled = task.cancel()

    print(f'canceled: {was_canceled}')

Running the example creates the main() coroutine and uses it as the entry point into the asyncio program.

The main() coroutine runs, first reporting a message.

It then gets the Task object for the currently running task, which refers to itself.

The main() coroutine then calls the cancel() method on the Task object that represents itself.

This raises a CancelledError exception in the coroutine, causing the asyncio program to terminate.

This highlights that indeed a task can cancel itself.

main coroutine started

canceled: True

Traceback (most recent call last):

  ...

asyncio.exceptions.CancelledError

Further Reading

This section provides additional resources that you may find helpful.

Python Asyncio Books

I also recommend the following books:

Guides

APIs

References

Takeaways

You now know how to get the current asyncio task in Python.

Do you have any questions?
Ask your questions in the comments below and I will do my best to answer.

Photo by William Chiesurin on Unsplash