Last Updated on November 14, 2023
Asyncio tasks are assigned default names when they are created.
Nevertheless, it can be beneficial to give tasks meaningful names. This can help when introspecting the asyncio event loop, when logging, and when debugging.
Task names can be made more meaningful by including task-specific data, such as ids.
In this tutorial, you will discover how to set and get the name of an asyncio task.
After completing this tutorial, you will know:
- Why setting a name for a task is helpful in asyncio programs.
- How to set a meaningful name for an asyncio task.
- How to retrieve the name of an asyncio task.
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:
1 2 3 |
... # 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 set and get task names.
Run loops using all CPUs, download your FREE book to learn how.
How to Set The Task Name
A task may have a name.
This name can be helpful if multiple tasks are created from the same coroutine and we need some way to tell them apart programmatically.
Using a task name can be used when logging, debugging, and conditionally performing operations on asyncio tasks.
The name of a task can be set when the task is created from a coroutine via the “name” argument to the asyncio.create_task() function.
For example:
1 2 3 |
... # create a task from a coroutine task = asyncio.create_task(task_coroutine(), name='MyTask') |
The name for the task can also be set via the set_name() method.
For example:
1 2 3 |
... # set the name of the task task.set_name('MyTask') |
We can retrieve the name of a task via the get_name() method.
For example:
1 2 3 |
... # get the name of a task name = task.get_name() |
Now that we are familiar with how to set and get the task name, let’s look at some examples.
Example of Getting the Default Task Name
Tasks are assigned a default name.
They have names with the format ‘Task-%d‘, where ‘%d‘ refers to the sequential task number created in the event loop.
For example, the first few tasks will have the default names Task-1, Task-2, Task-3, and so on.
We can explore the default name assigned to an asyncio task.
In this example, we will define a coroutine for a task that will report a message and block for a moment.
We will then define the main coroutine that will be used as the entry point to the asyncio program. The main coroutine will report a message, then create and schedule the task coroutine. It will then wait for the task to be completed.
Once completed, the main coroutine will print the task and its name.
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 27 28 |
# SuperFastPython.com # example of getting the default task name import asyncio # define a coroutine for a task async def task_coroutine(): # report a message print('executing the task') # block for a moment await asyncio.sleep(1) # custom coroutine async def main(): # report a message print('main coroutine started') # create and schedule the task task = asyncio.create_task(task_coroutine()) # wait for the task to complete await task # report the task print(task) # report the task name print(f'name: {task.get_name()}') # report a final message print('main coroutine done') # start the asyncio program asyncio.run(main()) |
Running the example starts the asyncio event loop and executes the main() coroutine.
The main() coroutine reports a message, then creates and schedules the task coroutine.
It then suspends and awaits the task to be complete.
The task runs, reports a message, and sleeps for a moment before terminating normally.
The main() coroutine resumes.
It prints a string representation of the task, which we can see shows the name of the task as ‘Task-2‘.
It then reports just the name of the task, which we can see matches the name included in the string representation of the task.
This example highlights that tasks are assigned a name by default that follows a predictable naming convention.
1 2 3 4 5 |
main coroutine started executing the task <Task finished name='Task-2' coro=<task_coroutine() done, defined at ...> result=None> name: Task-2 main coroutine done |
Next, let’s look at how we might set the name of a task when it is created.
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.
Example of Setting the Task Name When Creating
We can set the name of a task when it is created and scheduled via an argument to the create_task() function.
We can explore how to set a custom name for a task.
The example below updates the previous example to set a custom name for the task.
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 27 28 |
# SuperFastPython.com # example of setting the task name when it is created import asyncio # define a coroutine for a task async def task_coroutine(): # report a message print('executing the task') # block for a moment await asyncio.sleep(1) # custom coroutine async def main(): # report a message print('main coroutine started') # create and schedule the task task = asyncio.create_task(task_coroutine(), name="MyTask") # wait for the task to complete await task # report the task print(task) # report the task name print(f'name: {task.get_name()}') # report a final message print('main coroutine done') # start the asyncio program asyncio.run(main()) |
Running the example starts the asyncio event loop and executes the main() coroutine.
The main() coroutine reports a message, then creates and schedules the task coroutine with a custom name.
It then suspends and awaits the task to be completed.
The task runs, reports a message, and sleeps for a moment before terminating normally.
The main() coroutine resumes.
It prints a string representation of the task, which we can see shows the custom name of ‘MyTask‘.
It then reports just the name of the task, which we can see matches the name included in the string representation of the task.
This example highlights that we can assign a task a distinct name when it is created.
1 2 3 4 5 |
main coroutine started executing the task <Task finished name='MyTask' coro=<task_coroutine() done, defined at ...> result=None> name: MyTask main coroutine done |
Overwhelmed by the python concurrency APIs?
Find relief, download my FREE Python Concurrency Mind Maps
Example of Setting the Task Name While Running
We can set the name of the task after it has been created, such as when it is scheduled or running.
The example below updates the above example to first create and schedule the task, report the default name, then change the name while the task is running.
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 27 28 29 30 31 32 33 34 |
# SuperFastPython.com # example of setting the task name while it is running import asyncio # define a coroutine for a task async def task_coroutine(): # report a message print('executing the task') # block for a moment await asyncio.sleep(1) # custom coroutine async def main(): # report a message print('main coroutine started') # create and schedule the task task = asyncio.create_task(task_coroutine()) # report the task print(task) # wait a moment await asyncio.sleep(0.1) # set the name task.set_name('MyTask') # wait for the task to finish await task # report the task print(task) # report the task name print(f'name: {task.get_name()}') # report a final message print('main coroutine done') # start the asyncio program asyncio.run(main()) |
Running the example starts the asyncio event loop and executes the main() coroutine.
The main() coroutine reports a message, then creates and schedules the task coroutine.
It then prints a string representation of the task, showing the default task name.
The main() coroutine then waits a moment.
The task runs, reports a message, and sleeps for a moment.
The main() coroutine resumes and changes the name of the task. It then waits for the task to be completed.
The task resumes and then terminates normally.
The main() coroutine resumes. It reports a string representation of the task and the task name directly, both showing the custom name.
This highlights that we can change the name of a task while it is running.
1 2 3 4 5 6 |
main coroutine started <Task pending name='Task-2' coro=<task_coroutine() running at ...>> executing the task <Task finished name='MyTask' coro=<task_coroutine() done, defined at ...> result=None> name: MyTask main coroutine done |
Next, let’s look at how we might get the name of the task from within the task itself.
Example of Getting the Task Name Within the Task
We can get the currently running task in the event loop via the asyncio.current_task() function.
This function can be called within a coroutine to get a reference to the Task object that wraps it.
We can explore getting a Task instance within a coroutine and then using the task instance to allow the coroutine (task) to access its own name.
This can be helpful with tasks such as logging and operating conditionally based on the task name.
The example below updates the above example so that the task coroutine acquires the Task instance for itself and then reports the details of the task, including its name.
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 27 28 29 30 |
# SuperFastPython.com # example of getting the task name within the task import asyncio # define a coroutine for a task async def task_coroutine(): # report a message print('executing the task') # get the current task task = asyncio.current_task() # report the current task print(task) # report the name of the current task print(task.get_name()) # block for a moment await asyncio.sleep(1) # custom coroutine async def main(): # report a message print('main coroutine started') # create and schedule the task task = asyncio.create_task(task_coroutine()) # wait for the task to complete await task # report a final message print('main coroutine done') # start the asyncio program asyncio.run(main()) |
Running the example starts the asyncio event loop and executes the main() coroutine.
The main() coroutine reports a message, then creates and schedules the task coroutine.
It then suspends and awaits the task to be completed.
The task runs and reports a message. It then acquires the Task object that is currently running, which is the task that is executing the coroutine. It then reports the details of the task and its name, before sleeping and terminating normally.
The main() coroutine resumes and closes the program.
This example highlights that tasks are able to execute their own names.
1 2 3 4 5 |
main coroutine started executing the task <Task pending name='Task-2' coro=<task_coroutine() running at ...> cb=[Task.task_wakeup()]> Task-2 main coroutine done |
Further Reading
This section provides additional resources that you may find helpful.
Python Asyncio Books
- Python Asyncio Mastery, Jason Brownlee (my book!)
- Python Asyncio Jump-Start, Jason Brownlee.
- Python Asyncio Interview Questions, Jason Brownlee.
- Asyncio Module API Cheat Sheet
I also recommend the following books:
- Python Concurrency with asyncio, Matthew Fowler, 2022.
- Using Asyncio in Python, Caleb Hattingh, 2020.
- asyncio Recipes, Mohamed Mustapha Tahrioui, 2019.
Guides
APIs
- asyncio — Asynchronous I/O
- Asyncio Coroutines and Tasks
- Asyncio Streams
- Asyncio Subprocesses
- Asyncio Queues
- Asyncio Synchronization Primitives
References
Takeaways
You now know how to set and get the name of an 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 Stefan Rodriguez on Unsplash
Do you have any questions?