cpython: Close #12028: Make threading._get_ident() public, rename it to
http://hg.python.org/cpython/rev/5548197d1f22 changeset: 70530:5548197d1f22 user: Victor Stinner <victor.stinner@haypocalc.com> date: Mon May 30 23:02:52 2011 +0200 summary: Close #12028: Make threading._get_ident() public, rename it to threading.get_ident() and document it. This function was used by _thread.get_ident(). files: Doc/library/signal.rst | 7 ++--- Doc/library/threading.rst | 19 ++++++++++++++--- Lib/logging/__init__.py | 11 ++++----- Lib/reprlib.py | 2 +- Lib/test/lock_tests.py | 4 +- Lib/test/test_capi.py | 5 +-- Lib/test/test_signal.py | 4 +- Lib/test/test_sys.py | 6 ++-- Lib/test/test_threaded_import.py | 2 +- Lib/test/test_threading.py | 4 +- Lib/threading.py | 21 +++++++++---------- Misc/NEWS | 4 +++ 12 files changed, 50 insertions(+), 39 deletions(-) diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -187,10 +187,9 @@ Send the signal *signum* to the thread *thread_id*, another thread in the same process as the caller. The signal is asynchronously directed to thread. - *thread_id* can be read from the :attr:`~threading.Thread.ident` attribute - of :attr:`threading.Thread`. For example, - ``threading.current_thread().ident`` gives the identifier of the current - thread. + Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident` + attribute of :attr:`threading.Thread` to get a 'thread identifier' for + *thread_id*. If *signum* is 0, then no signal is sent, but error checking is still performed; this can be used to check if a thread is still running. diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -48,6 +48,17 @@ returned. +.. function:: get_ident() + + Return the 'thread identifier' of the current thread. This is a nonzero + integer. Its value has no direct meaning; it is intended as a magic cookie + to be used e.g. to index a dictionary of thread-specific data. Thread + identifiers may be recycled when a thread exits and another thread is + created. + + .. versionadded:: 3.3 + + .. function:: enumerate() Return a list of all :class:`Thread` objects currently alive. The list @@ -332,10 +343,10 @@ .. attribute:: ident The 'thread identifier' of this thread or ``None`` if the thread has not - been started. This is a nonzero integer. See the - :func:`thread.get_ident()` function. Thread identifiers may be recycled - when a thread exits and another thread is created. The identifier is - available even after the thread has exited. + been started. This is a nonzero integer. See the :func:`get_ident()` + function. Thread identifiers may be recycled when a thread exits and + another thread is created. The identifier is available even after the + thread has exited. .. method:: is_alive() diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -41,10 +41,9 @@ codecs = None try: - import _thread as thread import threading except ImportError: #pragma: no cover - thread = None + threading = None __author__ = "Vinay Sajip <vinay_sajip@red-dove.com>" __status__ = "production" @@ -199,7 +198,7 @@ #the lock would already have been acquired - so we need an RLock. #The same argument applies to Loggers and Manager.loggerDict. # -if thread: +if threading: _lock = threading.RLock() else: #pragma: no cover _lock = None @@ -278,8 +277,8 @@ self.created = ct self.msecs = (ct - int(ct)) * 1000 self.relativeCreated = (self.created - _startTime) * 1000 - if logThreads and thread: - self.thread = thread.get_ident() + if logThreads and threading: + self.thread = threading.get_ident() self.threadName = threading.current_thread().name else: # pragma: no cover self.thread = None @@ -773,7 +772,7 @@ """ Acquire a thread lock for serializing access to the underlying I/O. """ - if thread: + if threading: self.lock = threading.RLock() else: #pragma: no cover self.lock = None diff --git a/Lib/reprlib.py b/Lib/reprlib.py --- a/Lib/reprlib.py +++ b/Lib/reprlib.py @@ -5,7 +5,7 @@ import builtins from itertools import islice try: - from _thread import get_ident + from threading import get_ident except ImportError: from _dummy_thread import get_ident diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py --- a/Lib/test/lock_tests.py +++ b/Lib/test/lock_tests.py @@ -4,7 +4,7 @@ import sys import time -from _thread import start_new_thread, get_ident, TIMEOUT_MAX +from _thread import start_new_thread, TIMEOUT_MAX import threading import unittest @@ -31,7 +31,7 @@ self.finished = [] self._can_exit = not wait_before_exit def task(): - tid = get_ident() + tid = threading.get_ident() self.started.append(tid) try: f() diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -190,18 +190,17 @@ idents = [] def callback(): - idents.append(_thread.get_ident()) + idents.append(threading.get_ident()) _testcapi._test_thread_state(callback) a = b = callback time.sleep(1) # Check our main thread is in the list exactly 3 times. - if idents.count(_thread.get_ident()) != 3: + if idents.count(threading.get_ident()) != 3: raise support.TestFailed( "Couldn't find main thread correctly in the list") if threading: - import _thread import time TestThreadState() t = threading.Thread(target=TestThreadState) diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -557,7 +557,7 @@ def kill(self, signum): if self.has_pthread_kill: - tid = threading.current_thread().ident + tid = threading.get_ident() signal.pthread_kill(tid, signum) else: pid = os.getpid() @@ -589,7 +589,7 @@ 'need signal.pthread_kill()') def test_pthread_kill(self): signum = signal.SIGUSR1 - current = threading.current_thread().ident + current = threading.get_ident() old_handler = signal.signal(signum, self.handler) self.addCleanup(signal.signal, signum, old_handler) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -343,7 +343,7 @@ # Test sys._current_frames() in a WITH_THREADS build. @test.support.reap_threads def current_frames_with_threads(self): - import threading, _thread + import threading import traceback # Spawn a thread that blocks at a known place. Then the main @@ -357,7 +357,7 @@ g456() def g456(): - thread_info.append(_thread.get_ident()) + thread_info.append(threading.get_ident()) entered_g.set() leave_g.wait() @@ -373,7 +373,7 @@ d = sys._current_frames() - main_id = _thread.get_ident() + main_id = threading.get_ident() self.assertIn(main_id, d) self.assertIn(thread_id, d) diff --git a/Lib/test/test_threaded_import.py b/Lib/test/test_threaded_import.py --- a/Lib/test/test_threaded_import.py +++ b/Lib/test/test_threaded_import.py @@ -30,7 +30,7 @@ except Exception as e: errors.append(e.with_traceback(None)) finally: - done_tasks.append(thread.get_ident()) + done_tasks.append(threading.get_ident()) finished = len(done_tasks) == N if finished: done.set() diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -173,7 +173,7 @@ exception = ctypes.py_object(AsyncExc) # First check it works when setting the exception from the same thread. - tid = _thread.get_ident() + tid = threading.get_ident() try: result = set_async_exc(ctypes.c_long(tid), exception) @@ -202,7 +202,7 @@ class Worker(threading.Thread): def run(self): - self.id = _thread.get_ident() + self.id = threading.get_ident() self.finished = False try: diff --git a/Lib/threading.py b/Lib/threading.py --- a/Lib/threading.py +++ b/Lib/threading.py @@ -24,7 +24,7 @@ # Rename some stuff so "from threading import *" is safe _start_new_thread = _thread.start_new_thread _allocate_lock = _thread.allocate_lock -_get_ident = _thread.get_ident +get_ident = _thread.get_ident ThreadError = _thread.error try: _CRLock = _thread.RLock @@ -52,7 +52,7 @@ format = format % args # Issue #4188: calling current_thread() can incur an infinite # recursion if it has to create a DummyThread on the fly. - ident = _get_ident() + ident = get_ident() try: name = _active[ident].name except KeyError: @@ -110,7 +110,7 @@ self.__class__.__name__, owner, self._count) def acquire(self, blocking=True, timeout=-1): - me = _get_ident() + me = get_ident() if self._owner == me: self._count = self._count + 1 if __debug__: @@ -130,7 +130,7 @@ __enter__ = acquire def release(self): - if self._owner != _get_ident(): + if self._owner != get_ident(): raise RuntimeError("cannot release un-acquired lock") self._count = count = self._count - 1 if not count: @@ -166,7 +166,7 @@ return (count, owner) def _is_owned(self): - return self._owner == _get_ident() + return self._owner == get_ident() _PyRLock = _RLock @@ -714,7 +714,7 @@ raise def _set_ident(self): - self._ident = _get_ident() + self._ident = get_ident() def _bootstrap_inner(self): try: @@ -787,7 +787,7 @@ try: # We don't call self._delete() because it also # grabs _active_limbo_lock. - del _active[_get_ident()] + del _active[get_ident()] except: pass @@ -823,7 +823,7 @@ try: with _active_limbo_lock: - del _active[_get_ident()] + del _active[get_ident()] # There must not be any python code between the previous line # and after the lock is released. Otherwise a tracing function # could try to acquire the lock again in the same thread, (in @@ -1006,9 +1006,8 @@ def current_thread(): try: - return _active[_get_ident()] + return _active[get_ident()] except KeyError: - ##print "current_thread(): no current thread for", _get_ident() return _DummyThread() currentThread = current_thread @@ -1062,7 +1061,7 @@ if thread is current: # There is only one active thread. We reset the ident to # its new value since it can have changed. - ident = _get_ident() + ident = get_ident() thread._ident = ident # Any condition variables hanging off of the active thread may # be in an invalid state, so we reinitialize them. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -177,6 +177,10 @@ Library ------- +- Issue #12028: Make threading._get_ident() public, rename it to + threading.get_ident() and document it. This function was used by + _thread.get_ident(). + - Issue #12171: IncrementalEncoder.reset() of CJK codecs (multibytecodec) calls encreset() instead of decreset(). -- Repository URL: http://hg.python.org/cpython
On Tue, May 31, 2011 at 7:04 AM, victor.stinner <python-checkins@python.org> wrote:
+.. function:: get_ident() + + Return the 'thread identifier' of the current thread. This is a nonzero + integer. Its value has no direct meaning; it is intended as a magic cookie + to be used e.g. to index a dictionary of thread-specific data. Thread + identifiers may be recycled when a thread exits and another thread is + created.
That's not quite true - the Thread id isn't relinquished until the Thread object itself is destroyed, rather than when the underlying thread finishes execution (i.e. the lifecycle of a_thread.ident is the same as that of id(a_thread)). Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
+.. function:: get_ident() + + Return the 'thread identifier' of the current thread. This is a nonzero + integer. Its value has no direct meaning; it is intended as a magic cookie + to be used e.g. to index a dictionary of thread-specific data. Thread + identifiers may be recycled when a thread exits and another thread is + created.
That's not quite true - the Thread id isn't relinquished until the Thread object itself is destroyed, rather than when the underlying thread finishes execution (i.e. the lifecycle of a_thread.ident is the same as that of id(a_thread)).
I'm not sure I understand, Nick. Since threads are started detached, their thread ID (e.g. returned by pthread_self() on pthreads) can be reused as soon as the underlying OS thread exits (i.e. returns from Modules/_threadmodule.c:t_boostrap) : On a Linux kernel with NPTL: $ cat /tmp/test.py import threading def print_ident(): print(threading._get_ident()) t1 = threading.Thread(target=print_ident) t2 = threading.Thread(target=print_ident) t1.start() t1.join() t2.start() t2.join() print(id(t1), id(t2)) $ ./python /tmp/test.py -1211954272 -1211954272 (3085561228L, 3083093028L) I'm just curious, maybe I missed something? Thanks, cf
2011/5/31 Charles-François Natali <neologix@free.fr>:
+.. function:: get_ident() + + Return the 'thread identifier' of the current thread. This is a nonzero + integer. Its value has no direct meaning; it is intended as a magic cookie + to be used e.g. to index a dictionary of thread-specific data. Thread + identifiers may be recycled when a thread exits and another thread is + created.
That's not quite true - the Thread id isn't relinquished until the Thread object itself is destroyed, rather than when the underlying thread finishes execution (i.e. the lifecycle of a_thread.ident is the same as that of id(a_thread)).
I'm not sure I understand, Nick.
I was just wrong, but the wording is still confusing since it has been copied from _thread.ident. "Thread" means something other than "threading.Thread" in that module, while in the threading docs, it typically refers to the actual objects. With the change of module, there needs to be something to make it clearer that this is information related to os level threads. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
participants (3)
-
Charles-François Natali
-
Nick Coghlan
-
victor.stinner