Skip to content

In 3.13.* if custom asyncio task factory is set and no task name is provided to asyncio.create_task, task name provided by task factory is overwritten to "None". #130033

Closed

Description

@axzxc1236

Bug report

Bug description:

Code below illustrate a behavior change in 3.13 which I believe is a bug, which "Task-2" the task name becomes "None" while calling asyncio.current_task().get_name()

import asyncio

def task_factory(loop, *args, **kwargs):
    new_task = asyncio.Task(*args, **kwargs)
    name = new_task.get_name()
    # Python 3.9 to 3.13 prints name='Task-2'
    # 'Task-3' and 'Task-4' is also printed because loop is shutting down, which is not in the scope of (possible) bug
    print(f"{name=}")
    return new_task

async def print_task_name():
    current_task = asyncio.current_task()
    name = current_task.get_name()
    # Python 3.13 prints name='None' (but why does it print 'Task-2' before it's returned from task_factory() ?)
    # Python 3.9 to 3.12 prints name='Task-2'
    print(f"{name=}")

async def main():
    loop = asyncio.get_running_loop()
    loop.set_task_factory(task_factory)
    new_task = asyncio.create_task(print_task_name())
    await new_task

asyncio.run(main())

The source of bug/behavior change is that https://github.com/python/cpython/blob/v3.13.2/Lib/asyncio/base_events.py#L478 a set_name() is called unconditionally and version before 3.13 (e.g. https://github.com/python/cpython/blob/v3.12.9/Lib/asyncio/tasks.py#L70 ) setting task name to None does nothing which avoided the issue with custom task factory setting it's own task name.

If using a task factory, the task name can't be generated by task factory because it gets rewritten to name provided by asyncio.create_task(), which I think most people doesn't provide one.

Suggestion: check if name parameter is None before overwriting task name in create_task(), otherwise keep task name generated by task factory, and probably pass "name" parameter to task factory.

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Activity

  1. asvetlov commented on Feb 12, 2025

    @asvetlov
    Contributor

    Agree, loop.create_task() should call set_name() only if the name is not None.
    The bug exists in 3.13 only, the main branch has a different code and it should work fine.

  2. gvanrossum commented on Feb 12, 2025

    @gvanrossum
    Member

    Worth making a 3.13-specific fix though, right?

  3. asvetlov commented on Feb 13, 2025

    @asvetlov
    Contributor

    I'll do it

  4. asvetlov commented on Feb 13, 2025

    @asvetlov
    Contributor

    I think if we backport #128308, the fix covers the bug report well.

  5. asvetlov commented on Feb 13, 2025

    @asvetlov
    Contributor

    The backport #130084 is ready for review.

  6. asvetlov commented on Feb 14, 2025

    @asvetlov
    Contributor

    The fix was merged into the 3.13 branch.

  7. moved this from Todo to Done in asyncioon Feb 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    • Status
      Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions