summaryrefslogtreecommitdiffstats
path: root/Lib/asyncio/tasks.py
diff options
context:
space:
mode:
authorAlex Grönholm <alex.gronholm@nextday.fi>2018-08-08 21:06:47 (GMT)
committerYury Selivanov <yury@magic.io>2018-08-08 21:06:47 (GMT)
commitcca4eec3c0a67cbfeaf09182ea6c097a94891ff6 (patch)
tree0d04ad10797fa95e5e09f8b32e8aa9e0c50f6aac /Lib/asyncio/tasks.py
parent52dee687af3671a31f63d6432de0d9ef370fd7b0 (diff)
downloadcpython-cca4eec3c0a67cbfeaf09182ea6c097a94891ff6.zip
cpython-cca4eec3c0a67cbfeaf09182ea6c097a94891ff6.tar.gz
cpython-cca4eec3c0a67cbfeaf09182ea6c097a94891ff6.tar.bz2
bpo-34270: Make it possible to name asyncio tasks (GH-8547)
Co-authored-by: Antti Haapala <antti.haapala@anttipatterns.com>
Diffstat (limited to 'Lib/asyncio/tasks.py')
-rw-r--r--Lib/asyncio/tasks.py35
1 files changed, 32 insertions, 3 deletions
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 72792a2..03d71d3 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -13,6 +13,7 @@ import concurrent.futures
import contextvars
import functools
import inspect
+import itertools
import types
import warnings
import weakref
@@ -23,6 +24,11 @@ from . import events
from . import futures
from .coroutines import coroutine
+# Helper to generate new task names
+# This uses itertools.count() instead of a "+= 1" operation because the latter
+# is not thread safe. See bpo-11866 for a longer explanation.
+_task_name_counter = itertools.count(1).__next__
+
def current_task(loop=None):
"""Return a currently executed task."""
@@ -48,6 +54,16 @@ def _all_tasks_compat(loop=None):
return {t for t in _all_tasks if futures._get_loop(t) is loop}
+def _set_task_name(task, name):
+ if name is not None:
+ try:
+ set_name = task.set_name
+ except AttributeError:
+ pass
+ else:
+ set_name(name)
+
+
class Task(futures._PyFuture): # Inherit Python Task implementation
# from a Python Future implementation.
@@ -94,7 +110,7 @@ class Task(futures._PyFuture): # Inherit Python Task implementation
stacklevel=2)
return _all_tasks_compat(loop)
- def __init__(self, coro, *, loop=None):
+ def __init__(self, coro, *, loop=None, name=None):
super().__init__(loop=loop)
if self._source_traceback:
del self._source_traceback[-1]
@@ -104,6 +120,11 @@ class Task(futures._PyFuture): # Inherit Python Task implementation
self._log_destroy_pending = False
raise TypeError(f"a coroutine was expected, got {coro!r}")
+ if name is None:
+ self._name = f'Task-{_task_name_counter()}'
+ else:
+ self._name = str(name)
+
self._must_cancel = False
self._fut_waiter = None
self._coro = coro
@@ -126,6 +147,12 @@ class Task(futures._PyFuture): # Inherit Python Task implementation
def _repr_info(self):
return base_tasks._task_repr_info(self)
+ def get_name(self):
+ return self._name
+
+ def set_name(self, value):
+ self._name = str(value)
+
def set_result(self, result):
raise RuntimeError('Task does not support set_result operation')
@@ -312,13 +339,15 @@ else:
Task = _CTask = _asyncio.Task
-def create_task(coro):
+def create_task(coro, *, name=None):
"""Schedule the execution of a coroutine object in a spawn task.
Return a Task object.
"""
loop = events.get_running_loop()
- return loop.create_task(coro)
+ task = loop.create_task(coro)
+ _set_task_name(task, name)
+ return task
# wait() and as_completed() similar to those in PEP 3148.