Multiple threads may be given the same name. The initial name is set by
the constructor.
+ On some platforms, the thread name is set at the operating system level
+ when the thread starts, so that it is visible in task managers.
+ This name may be truncated to fit in a system-specific limit (for example,
+ 15 bytes on Linux or 63 bytes on macOS).
+
+ Changes to *name* are only reflected at the OS level when the currently
+ running thread is renamed. (Setting the *name* attribute of a
+ different thread only updates the Python Thread object.)
+
+ .. versionchanged:: 3.14
+ Set the operating system thread name.
+
.. method:: getName()
setName()
self.assertEqual(work_name, expected,
f"{len(work_name)=} and {len(expected)=}")
+ @unittest.skipUnless(hasattr(_thread, 'set_name'), "missing _thread.set_name")
+ @unittest.skipUnless(hasattr(_thread, '_get_name'), "missing _thread._get_name")
+ def test_change_name(self):
+ # Change the name of a thread while the thread is running
+
+ name1 = None
+ name2 = None
+ def work():
+ nonlocal name1, name2
+ name1 = _thread._get_name()
+ threading.current_thread().name = "new name"
+ name2 = _thread._get_name()
+
+ thread = threading.Thread(target=work, name="name")
+ thread.start()
+ thread.join()
+ self.assertEqual(name1, "name")
+ self.assertEqual(name2, "new name")
+
class InterruptMainTests(unittest.TestCase):
def check_interrupt_main_with_signal_handler(self, signum):
def _set_native_id(self):
self._native_id = get_native_id()
+ def _set_os_name(self):
+ if _set_name is None or not self._name:
+ return
+ try:
+ _set_name(self._name)
+ except OSError:
+ pass
+
def _bootstrap_inner(self):
try:
self._set_ident()
if _HAVE_THREAD_NATIVE_ID:
self._set_native_id()
- if _set_name is not None and self._name:
- try:
- _set_name(self._name)
- except OSError:
- pass
+ self._set_os_name()
self._started.set()
with _active_limbo_lock:
_active[self._ident] = self
def name(self, name):
assert self._initialized, "Thread.__init__() not called"
self._name = str(name)
+ if get_ident() == self._ident:
+ self._set_os_name()
@property
def ident(self):
#ifdef PYTHREAD_NAME_MAXLEN
// Truncate to PYTHREAD_NAME_MAXLEN bytes + the NUL byte if needed
- size_t len = PyBytes_GET_SIZE(name_encoded);
- if (len > PYTHREAD_NAME_MAXLEN) {
+ if (PyBytes_GET_SIZE(name_encoded) > PYTHREAD_NAME_MAXLEN) {
PyObject *truncated;
truncated = PyBytes_FromStringAndSize(PyBytes_AS_STRING(name_encoded),
PYTHREAD_NAME_MAXLEN);