Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
threading.py1643 linesDownload Raw Back to Lib
1"""Thread module emulating a subset of Java's threading model."""2 3import os as _os4import sys as _sys5import _thread6import _contextvars7 8from time import monotonic as _time9from _weakrefset import WeakSet10from itertools import count as _count11try:12    from _collections import deque as _deque13except ImportError:14    from collections import deque as _deque15 16# Note regarding PEP 8 compliant names17#  This threading model was originally inspired by Java, and inherited18# the convention of camelCase function and method names from that19# language. Those original names are not in any imminent danger of20# being deprecated (even for Py3k),so this module provides them as an21# alias for the PEP 8 compliant names22# Note that using the new PEP 8 compliant names facilitates substitution23# with the multiprocessing module, which doesn't provide the old24# Java inspired names.25 26__all__ = ['get_ident', 'active_count', 'Condition', 'current_thread',27           'enumerate', 'main_thread', 'TIMEOUT_MAX',28           'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread',29           'Barrier', 'BrokenBarrierError', 'Timer', 'ThreadError',30           'setprofile', 'settrace', 'local', 'stack_size',31           'excepthook', 'ExceptHookArgs', 'gettrace', 'getprofile',32           'setprofile_all_threads','settrace_all_threads']33 34# Rename some stuff so "from threading import *" is safe35_start_joinable_thread = _thread.start_joinable_thread36_daemon_threads_allowed = _thread.daemon_threads_allowed37_allocate_lock = _thread.allocate_lock38_LockType = _thread.LockType39_thread_shutdown = _thread._shutdown40_make_thread_handle = _thread._make_thread_handle41_ThreadHandle = _thread._ThreadHandle42get_ident = _thread.get_ident43_get_main_thread_ident = _thread._get_main_thread_ident44_is_main_interpreter = _thread._is_main_interpreter45try:46    get_native_id = _thread.get_native_id47    _HAVE_THREAD_NATIVE_ID = True48    __all__.append('get_native_id')49except AttributeError:50    _HAVE_THREAD_NATIVE_ID = False51try:52    _set_name = _thread.set_name53except AttributeError:54    _set_name = None55ThreadError = _thread.error56try:57    _CRLock = _thread.RLock58except AttributeError:59    _CRLock = None60TIMEOUT_MAX = _thread.TIMEOUT_MAX61del _thread62 63# get thread-local implementation, either from the thread64# module, or from the python fallback65 66try:67    from _thread import _local as local68except ImportError:69    from _threading_local import local70 71# Support for profile and trace hooks72 73_profile_hook = None74_trace_hook = None75 76def setprofile(func):77    """Set a profile function for all threads started from the threading module.78 79    The func will be passed to sys.setprofile() for each thread, before its80    run() method is called.81    """82    global _profile_hook83    _profile_hook = func84 85def setprofile_all_threads(func):86    """Set a profile function for all threads started from the threading module87    and all Python threads that are currently executing.88 89    The func will be passed to sys.setprofile() for each thread, before its90    run() method is called.91    """92    setprofile(func)93    _sys._setprofileallthreads(func)94 95def getprofile():96    """Get the profiler function as set by threading.setprofile()."""97    return _profile_hook98 99def settrace(func):100    """Set a trace function for all threads started from the threading module.101 102    The func will be passed to sys.settrace() for each thread, before its run()103    method is called.104    """105    global _trace_hook106    _trace_hook = func107 108def settrace_all_threads(func):109    """Set a trace function for all threads started from the threading module110    and all Python threads that are currently executing.111 112    The func will be passed to sys.settrace() for each thread, before its run()113    method is called.114    """115    settrace(func)116    _sys._settraceallthreads(func)117 118def gettrace():119    """Get the trace function as set by threading.settrace()."""120    return _trace_hook121 122# Synchronization classes123 124Lock = _LockType125 126def RLock(*args, **kwargs):127    """Factory function that returns a new reentrant lock.128 129    A reentrant lock must be released by the thread that acquired it. Once a130    thread has acquired a reentrant lock, the same thread may acquire it again131    without blocking; the thread must release it once for each time it has132    acquired it.133 134    """135    if args or kwargs:136        import warnings137        warnings.warn(138            'Passing arguments to RLock is deprecated and will be removed in 3.15',139            DeprecationWarning,140            stacklevel=2,141        )142    if _CRLock is None:143        return _PyRLock(*args, **kwargs)144    return _CRLock(*args, **kwargs)145 146class _RLock:147    """This class implements reentrant lock objects.148 149    A reentrant lock must be released by the thread that acquired it. Once a150    thread has acquired a reentrant lock, the same thread may acquire it151    again without blocking; the thread must release it once for each time it152    has acquired it.153 154    """155 156    def __init__(self):157        self._block = _allocate_lock()158        self._owner = None159        self._count = 0160 161    def __repr__(self):162        owner = self._owner163        try:164            owner = _active[owner].name165        except KeyError:166            pass167        return "<%s %s.%s object owner=%r count=%d at %s>" % (168            "locked" if self.locked() else "unlocked",169            self.__class__.__module__,170            self.__class__.__qualname__,171            owner,172            self._count,173            hex(id(self))174        )175 176    def _at_fork_reinit(self):177        self._block._at_fork_reinit()178        self._owner = None179        self._count = 0180 181    def acquire(self, blocking=True, timeout=-1):182        """Acquire a lock, blocking or non-blocking.183 184        When invoked without arguments: if this thread already owns the lock,185        increment the recursion level by one, and return immediately. Otherwise,186        if another thread owns the lock, block until the lock is unlocked. Once187        the lock is unlocked (not owned by any thread), then grab ownership, set188        the recursion level to one, and return. If more than one thread is189        blocked waiting until the lock is unlocked, only one at a time will be190        able to grab ownership of the lock. There is no return value in this191        case.192 193        When invoked with the blocking argument set to true, do the same thing194        as when called without arguments, and return true.195 196        When invoked with the blocking argument set to false, do not block. If a197        call without an argument would block, return false immediately;198        otherwise, do the same thing as when called without arguments, and199        return true.200 201        When invoked with the floating-point timeout argument set to a positive202        value, block for at most the number of seconds specified by timeout203        and as long as the lock cannot be acquired.  Return true if the lock has204        been acquired, false if the timeout has elapsed.205 206        """207        me = get_ident()208        if self._owner == me:209            self._count += 1210            return 1211        rc = self._block.acquire(blocking, timeout)212        if rc:213            self._owner = me214            self._count = 1215        return rc216 217    __enter__ = acquire218 219    def release(self):220        """Release a lock, decrementing the recursion level.221 222        If after the decrement it is zero, reset the lock to unlocked (not owned223        by any thread), and if any other threads are blocked waiting for the224        lock to become unlocked, allow exactly one of them to proceed. If after225        the decrement the recursion level is still nonzero, the lock remains226        locked and owned by the calling thread.227 228        Only call this method when the calling thread owns the lock. A229        RuntimeError is raised if this method is called when the lock is230        unlocked.231 232        There is no return value.233 234        """235        if self._owner != get_ident():236            raise RuntimeError("cannot release un-acquired lock")237        self._count = count = self._count - 1238        if not count:239            self._owner = None240            self._block.release()241 242    def __exit__(self, t, v, tb):243        self.release()244 245    def locked(self):246        """Return whether this object is locked."""247        return self._block.locked()248 249    # Internal methods used by condition variables250 251    def _acquire_restore(self, state):252        self._block.acquire()253        self._count, self._owner = state254 255    def _release_save(self):256        if self._count == 0:257            raise RuntimeError("cannot release un-acquired lock")258        count = self._count259        self._count = 0260        owner = self._owner261        self._owner = None262        self._block.release()263        return (count, owner)264 265    def _is_owned(self):266        return self._owner == get_ident()267 268    # Internal method used for reentrancy checks269 270    def _recursion_count(self):271        if self._owner != get_ident():272            return 0273        return self._count274 275_PyRLock = _RLock276 277 278class Condition:279    """Class that implements a condition variable.280 281    A condition variable allows one or more threads to wait until they are282    notified by another thread.283 284    If the lock argument is given and not None, it must be a Lock or RLock285    object, and it is used as the underlying lock. Otherwise, a new RLock object286    is created and used as the underlying lock.287 288    """289 290    def __init__(self, lock=None):291        if lock is None:292            lock = RLock()293        self._lock = lock294        # Export the lock's acquire(), release(), and locked() methods295        self.acquire = lock.acquire296        self.release = lock.release297        self.locked = lock.locked298        # If the lock defines _release_save() and/or _acquire_restore(),299        # these override the default implementations (which just call300        # release() and acquire() on the lock).  Ditto for _is_owned().301        if hasattr(lock, '_release_save'):302            self._release_save = lock._release_save303        if hasattr(lock, '_acquire_restore'):304            self._acquire_restore = lock._acquire_restore305        if hasattr(lock, '_is_owned'):306            self._is_owned = lock._is_owned307        self._waiters = _deque()308 309    def _at_fork_reinit(self):310        self._lock._at_fork_reinit()311        self._waiters.clear()312 313    def __enter__(self):314        return self._lock.__enter__()315 316    def __exit__(self, *args):317        return self._lock.__exit__(*args)318 319    def __repr__(self):320        return "<Condition(%s, %d)>" % (self._lock, len(self._waiters))321 322    def _release_save(self):323        self._lock.release()           # No state to save324 325    def _acquire_restore(self, x):326        self._lock.acquire()           # Ignore saved state327 328    def _is_owned(self):329        # Return True if lock is owned by current_thread.330        # This method is called only if _lock doesn't have _is_owned().331        if self._lock.acquire(False):332            self._lock.release()333            return False334        else:335            return True336 337    def wait(self, timeout=None):338        """Wait until notified or until a timeout occurs.339 340        If the calling thread has not acquired the lock when this method is341        called, a RuntimeError is raised.342 343        This method releases the underlying lock, and then blocks until it is344        awakened by a notify() or notify_all() call for the same condition345        variable in another thread, or until the optional timeout occurs. Once346        awakened or timed out, it re-acquires the lock and returns.347 348        When the timeout argument is present and not None, it should be a349        floating-point number specifying a timeout for the operation in seconds350        (or fractions thereof).351 352        When the underlying lock is an RLock, it is not released using its353        release() method, since this may not actually unlock the lock when it354        was acquired multiple times recursively. Instead, an internal interface355        of the RLock class is used, which really unlocks it even when it has356        been recursively acquired several times. Another internal interface is357        then used to restore the recursion level when the lock is reacquired.358 359        """360        if not self._is_owned():361            raise RuntimeError("cannot wait on un-acquired lock")362        waiter = _allocate_lock()363        waiter.acquire()364        self._waiters.append(waiter)365        saved_state = self._release_save()366        gotit = False367        try:    # restore state no matter what (e.g., KeyboardInterrupt)368            if timeout is None:369                waiter.acquire()370                gotit = True371            else:372                if timeout > 0:373                    gotit = waiter.acquire(True, timeout)374                else:375                    gotit = waiter.acquire(False)376            return gotit377        finally:378            self._acquire_restore(saved_state)379            if not gotit:380                try:381                    self._waiters.remove(waiter)382                except ValueError:383                    pass384 385    def wait_for(self, predicate, timeout=None):386        """Wait until a condition evaluates to True.387 388        predicate should be a callable which result will be interpreted as a389        boolean value.  A timeout may be provided giving the maximum time to390        wait.391 392        """393        endtime = None394        waittime = timeout395        result = predicate()396        while not result:397            if waittime is not None:398                if endtime is None:399                    endtime = _time() + waittime400                else:401                    waittime = endtime - _time()402                    if waittime <= 0:403                        break404            self.wait(waittime)405            result = predicate()406        return result407 408    def notify(self, n=1):409        """Wake up one or more threads waiting on this condition, if any.410 411        If the calling thread has not acquired the lock when this method is412        called, a RuntimeError is raised.413 414        This method wakes up at most n of the threads waiting for the condition415        variable; it is a no-op if no threads are waiting.416 417        """418        if not self._is_owned():419            raise RuntimeError("cannot notify on un-acquired lock")420        waiters = self._waiters421        while waiters and n > 0:422            waiter = waiters[0]423            try:424                waiter.release()425            except RuntimeError:426                # gh-92530: The previous call of notify() released the lock,427                # but was interrupted before removing it from the queue.428                # It can happen if a signal handler raises an exception,429                # like CTRL+C which raises KeyboardInterrupt.430                pass431            else:432                n -= 1433            try:434                waiters.remove(waiter)435            except ValueError:436                pass437 438    def notify_all(self):439        """Wake up all threads waiting on this condition.440 441        If the calling thread has not acquired the lock when this method442        is called, a RuntimeError is raised.443 444        """445        self.notify(len(self._waiters))446 447    def notifyAll(self):448        """Wake up all threads waiting on this condition.449 450        This method is deprecated, use notify_all() instead.451 452        """453        import warnings454        warnings.warn('notifyAll() is deprecated, use notify_all() instead',455                      DeprecationWarning, stacklevel=2)456        self.notify_all()457 458 459class Semaphore:460    """This class implements semaphore objects.461 462    Semaphores manage a counter representing the number of release() calls minus463    the number of acquire() calls, plus an initial value. The acquire() method464    blocks if necessary until it can return without making the counter465    negative. If not given, value defaults to 1.466 467    """468 469    # After Tim Peters' semaphore class, but not quite the same (no maximum)470 471    def __init__(self, value=1):472        if value < 0:473            raise ValueError("semaphore initial value must be >= 0")474        self._cond = Condition(Lock())475        self._value = value476 477    def __repr__(self):478        cls = self.__class__479        return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:"480                f" value={self._value}>")481 482    def acquire(self, blocking=True, timeout=None):483        """Acquire a semaphore, decrementing the internal counter by one.484 485        When invoked without arguments: if the internal counter is larger than486        zero on entry, decrement it by one and return immediately. If it is zero487        on entry, block, waiting until some other thread has called release() to488        make it larger than zero. This is done with proper interlocking so that489        if multiple acquire() calls are blocked, release() will wake exactly one490        of them up. The implementation may pick one at random, so the order in491        which blocked threads are awakened should not be relied on. There is no492        return value in this case.493 494        When invoked with blocking set to true, do the same thing as when called495        without arguments, and return true.496 497        When invoked with blocking set to false, do not block. If a call without498        an argument would block, return false immediately; otherwise, do the499        same thing as when called without arguments, and return true.500 501        When invoked with a timeout other than None, it will block for at502        most timeout seconds.  If acquire does not complete successfully in503        that interval, return false.  Return true otherwise.504 505        """506        if not blocking and timeout is not None:507            raise ValueError("can't specify timeout for non-blocking acquire")508        rc = False509        endtime = None510        with self._cond:511            while self._value == 0:512                if not blocking:513                    break514                if timeout is not None:515                    if endtime is None:516                        endtime = _time() + timeout517                    else:518                        timeout = endtime - _time()519                        if timeout <= 0:520                            break521                self._cond.wait(timeout)522            else:523                self._value -= 1524                rc = True525        return rc526 527    __enter__ = acquire528 529    def release(self, n=1):530        """Release a semaphore, incrementing the internal counter by one or more.531 532        When the counter is zero on entry and another thread is waiting for it533        to become larger than zero again, wake up that thread.534 535        """536        if n < 1:537            raise ValueError('n must be one or more')538        with self._cond:539            self._value += n540            self._cond.notify(n)541 542    def __exit__(self, t, v, tb):543        self.release()544 545 546class BoundedSemaphore(Semaphore):547    """Implements a bounded semaphore.548 549    A bounded semaphore checks to make sure its current value doesn't exceed its550    initial value. If it does, ValueError is raised. In most situations551    semaphores are used to guard resources with limited capacity.552 553    If the semaphore is released too many times it's a sign of a bug. If not554    given, value defaults to 1.555 556    Like regular semaphores, bounded semaphores manage a counter representing557    the number of release() calls minus the number of acquire() calls, plus an558    initial value. The acquire() method blocks if necessary until it can return559    without making the counter negative. If not given, value defaults to 1.560 561    """562 563    def __init__(self, value=1):564        super().__init__(value)565        self._initial_value = value566 567    def __repr__(self):568        cls = self.__class__569        return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:"570                f" value={self._value}/{self._initial_value}>")571 572    def release(self, n=1):573        """Release a semaphore, incrementing the internal counter by one or more.574 575        When the counter is zero on entry and another thread is waiting for it576        to become larger than zero again, wake up that thread.577 578        If the number of releases exceeds the number of acquires,579        raise a ValueError.580 581        """582        if n < 1:583            raise ValueError('n must be one or more')584        with self._cond:585            if self._value + n > self._initial_value:586                raise ValueError("Semaphore released too many times")587            self._value += n588            self._cond.notify(n)589 590 591class Event:592    """Class implementing event objects.593 594    Events manage a flag that can be set to true with the set() method and reset595    to false with the clear() method. The wait() method blocks until the flag is596    true.  The flag is initially false.597 598    """599 600    # After Tim Peters' event class (without is_posted())601 602    def __init__(self):603        self._cond = Condition(Lock())604        self._flag = False605 606    def __repr__(self):607        cls = self.__class__608        status = 'set' if self._flag else 'unset'609        return f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}: {status}>"610 611    def _at_fork_reinit(self):612        # Private method called by Thread._after_fork()613        self._cond._at_fork_reinit()614 615    def is_set(self):616        """Return true if and only if the internal flag is true."""617        return self._flag618 619    def isSet(self):620        """Return true if and only if the internal flag is true.621 622        This method is deprecated, use is_set() instead.623 624        """625        import warnings626        warnings.warn('isSet() is deprecated, use is_set() instead',627                      DeprecationWarning, stacklevel=2)628        return self.is_set()629 630    def set(self):631        """Set the internal flag to true.632 633        All threads waiting for it to become true are awakened. Threads634        that call wait() once the flag is true will not block at all.635 636        """637        with self._cond:638            self._flag = True639            self._cond.notify_all()640 641    def clear(self):642        """Reset the internal flag to false.643 644        Subsequently, threads calling wait() will block until set() is called to645        set the internal flag to true again.646 647        """648        with self._cond:649            self._flag = False650 651    def wait(self, timeout=None):652        """Block until the internal flag is true.653 654        If the internal flag is true on entry, return immediately. Otherwise,655        block until another thread calls set() to set the flag to true, or until656        the optional timeout occurs.657 658        When the timeout argument is present and not None, it should be a659        floating-point number specifying a timeout for the operation in seconds660        (or fractions thereof).661 662        This method returns the internal flag on exit, so it will always return663        ``True`` except if a timeout is given and the operation times out, when664        it will return ``False``.665 666        """667        with self._cond:668            signaled = self._flag669            if not signaled:670                signaled = self._cond.wait(timeout)671            return signaled672 673 674# A barrier class.  Inspired in part by the pthread_barrier_* api and675# the CyclicBarrier class from Java.  See676# http://sourceware.org/pthreads-win32/manual/pthread_barrier_init.html and677# http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/678#        CyclicBarrier.html679# for information.680# We maintain two main states, 'filling' and 'draining' enabling the barrier681# to be cyclic.  Threads are not allowed into it until it has fully drained682# since the previous cycle.  In addition, a 'resetting' state exists which is683# similar to 'draining' except that threads leave with a BrokenBarrierError,684# and a 'broken' state in which all threads get the exception.685class Barrier:686    """Implements a Barrier.687 688    Useful for synchronizing a fixed number of threads at known synchronization689    points.  Threads block on 'wait()' and are simultaneously awoken once they690    have all made that call.691 692    """693 694    def __init__(self, parties, action=None, timeout=None):695        """Create a barrier, initialised to 'parties' threads.696 697        'action' is a callable which, when supplied, will be called by one of698        the threads after they have all entered the barrier and just prior to699        releasing them all. If a 'timeout' is provided, it is used as the700        default for all subsequent 'wait()' calls.701 702        """703        if parties < 1:704            raise ValueError("parties must be >= 1")705        self._cond = Condition(Lock())706        self._action = action707        self._timeout = timeout708        self._parties = parties709        self._state = 0  # 0 filling, 1 draining, -1 resetting, -2 broken710        self._count = 0711 712    def __repr__(self):713        cls = self.__class__714        if self.broken:715            return f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}: broken>"716        return (f"<{cls.__module__}.{cls.__qualname__} at {id(self):#x}:"717                f" waiters={self.n_waiting}/{self.parties}>")718 719    def wait(self, timeout=None):720        """Wait for the barrier.721 722        When the specified number of threads have started waiting, they are all723        simultaneously awoken. If an 'action' was provided for the barrier, one724        of the threads will have executed that callback prior to returning.725        Returns an individual index number from 0 to 'parties-1'.726 727        """728        if timeout is None:729            timeout = self._timeout730        with self._cond:731            self._enter() # Block while the barrier drains.732            index = self._count733            self._count += 1734            try:735                if index + 1 == self._parties:736                    # We release the barrier737                    self._release()738                else:739                    # We wait until someone releases us740                    self._wait(timeout)741                return index742            finally:743                self._count -= 1744                # Wake up any threads waiting for barrier to drain.745                self._exit()746 747    # Block until the barrier is ready for us, or raise an exception748    # if it is broken.749    def _enter(self):750        while self._state in (-1, 1):751            # It is draining or resetting, wait until done752            self._cond.wait()753        #see if the barrier is in a broken state754        if self._state < 0:755            raise BrokenBarrierError756        assert self._state == 0757 758    # Optionally run the 'action' and release the threads waiting759    # in the barrier.760    def _release(self):761        try:762            if self._action:763                self._action()764            # enter draining state765            self._state = 1766            self._cond.notify_all()767        except:768            #an exception during the _action handler.  Break and reraise769            self._break()770            raise771 772    # Wait in the barrier until we are released.  Raise an exception773    # if the barrier is reset or broken.774    def _wait(self, timeout):775        if not self._cond.wait_for(lambda : self._state != 0, timeout):776            #timed out.  Break the barrier777            self._break()778            raise BrokenBarrierError779        if self._state < 0:780            raise BrokenBarrierError781        assert self._state == 1782 783    # If we are the last thread to exit the barrier, signal any threads784    # waiting for the barrier to drain.785    def _exit(self):786        if self._count == 0:787            if self._state in (-1, 1):788                #resetting or draining789                self._state = 0790                self._cond.notify_all()791 792    def reset(self):793        """Reset the barrier to the initial state.794 795        Any threads currently waiting will get the BrokenBarrier exception796        raised.797 798        """799        with self._cond:800            if self._count > 0:801                if self._state == 0:802                    #reset the barrier, waking up threads803                    self._state = -1804                elif self._state == -2:805                    #was broken, set it to reset state806                    #which clears when the last thread exits807                    self._state = -1808            else:809                self._state = 0810            self._cond.notify_all()811 812    def abort(self):813        """Place the barrier into a 'broken' state.814 815        Useful in case of error.  Any currently waiting threads and threads816        attempting to 'wait()' will have BrokenBarrierError raised.817 818        """819        with self._cond:820            self._break()821 822    def _break(self):823        # An internal error was detected.  The barrier is set to824        # a broken state all parties awakened.825        self._state = -2826        self._cond.notify_all()827 828    @property829    def parties(self):830        """Return the number of threads required to trip the barrier."""831        return self._parties832 833    @property834    def n_waiting(self):835        """Return the number of threads currently waiting at the barrier."""836        # We don't need synchronization here since this is an ephemeral result837        # anyway.  It returns the correct value in the steady state.838        if self._state == 0:839            return self._count840        return 0841 842    @property843    def broken(self):844        """Return True if the barrier is in a broken state."""845        return self._state == -2846 847# exception raised by the Barrier class848class BrokenBarrierError(RuntimeError):849    pass850 851 852# Helper to generate new thread names853_counter = _count(1).__next__854def _newname(name_template):855    return name_template % _counter()856 857# Active thread administration.858#859# bpo-44422: Use a reentrant lock to allow reentrant calls to functions like860# threading.enumerate().861_active_limbo_lock = RLock()862_active = {}    # maps thread id to Thread object863_limbo = {}864_dangling = WeakSet()865 866 867# Main class for threads868 869class Thread:870    """A class that represents a thread of control.871 872    This class can be safely subclassed in a limited fashion. There are two ways873    to specify the activity: by passing a callable object to the constructor, or874    by overriding the run() method in a subclass.875 876    """877 878    _initialized = False879 880    def __init__(self, group=None, target=None, name=None,881                 args=(), kwargs=None, *, daemon=None, context=None):882        """This constructor should always be called with keyword arguments. Arguments are:883 884        *group* should be None; reserved for future extension when a ThreadGroup885        class is implemented.886 887        *target* is the callable object to be invoked by the run()888        method. Defaults to None, meaning nothing is called.889 890        *name* is the thread name. By default, a unique name is constructed of891        the form "Thread-N" where N is a small decimal number.892 893        *args* is a list or tuple of arguments for the target invocation. Defaults to ().894 895        *kwargs* is a dictionary of keyword arguments for the target896        invocation. Defaults to {}.897 898        *context* is the contextvars.Context value to use for the thread.899        The default value is None, which means to check900        sys.flags.thread_inherit_context.  If that flag is true, use a copy901        of the context of the caller.  If false, use an empty context.  To902        explicitly start with an empty context, pass a new instance of903        contextvars.Context().  To explicitly start with a copy of the current904        context, pass the value from contextvars.copy_context().905 906        If a subclass overrides the constructor, it must make sure to invoke907        the base class constructor (Thread.__init__()) before doing anything908        else to the thread.909 910        """911        assert group is None, "group argument must be None for now"912        if kwargs is None:913            kwargs = {}914        if name:915            name = str(name)916        else:917            name = _newname("Thread-%d")918            if target is not None:919                try:920                    target_name = target.__name__921                    name += f" ({target_name})"922                except AttributeError:923                    pass924 925        self._target = target926        self._name = name927        self._args = args928        self._kwargs = kwargs929        if daemon is not None:930            if daemon and not _daemon_threads_allowed():931                raise RuntimeError('daemon threads are disabled in this (sub)interpreter')932            self._daemonic = daemon933        else:934            self._daemonic = current_thread().daemon935        self._context = context936        self._ident = None937        if _HAVE_THREAD_NATIVE_ID:938            self._native_id = None939        self._os_thread_handle = _ThreadHandle()940        self._started = Event()941        self._initialized = True942        # Copy of sys.stderr used by self._invoke_excepthook()943        self._stderr = _sys.stderr944        self._invoke_excepthook = _make_invoke_excepthook()945        # For debugging and _after_fork()946        _dangling.add(self)947 948    def _after_fork(self, new_ident=None):949        # Private!  Called by threading._after_fork().950        self._started._at_fork_reinit()951        if new_ident is not None:952            # This thread is alive.953            self._ident = new_ident954            assert self._os_thread_handle.ident == new_ident955            if _HAVE_THREAD_NATIVE_ID:956                self._set_native_id()957        else:958            # Otherwise, the thread is dead, Jim.  _PyThread_AfterFork()959            # already marked our handle done.960            pass961 962    def __repr__(self):963        assert self._initialized, "Thread.__init__() was not called"964        status = "initial"965        if self._started.is_set():966            status = "started"967        if self._os_thread_handle.is_done():968            status = "stopped"969        if self._daemonic:970            status += " daemon"971        if self._ident is not None:972            status += " %s" % self._ident973        return "<%s(%s, %s)>" % (self.__class__.__name__, self._name, status)974 975    def start(self):976        """Start the thread's activity.977 978        It must be called at most once per thread object. It arranges for the979        object's run() method to be invoked in a separate thread of control.980 981        This method will raise a RuntimeError if called more than once on the982        same thread object.983 984        """985        if not self._initialized:986            raise RuntimeError("thread.__init__() not called")987 988        if self._started.is_set():989            raise RuntimeError("threads can only be started once")990 991        with _active_limbo_lock:992            _limbo[self] = self993 994        if self._context is None:995            # No context provided996            if _sys.flags.thread_inherit_context:997                # start with a copy of the context of the caller998                self._context = _contextvars.copy_context()999            else:1000                # start with an empty context1001                self._context = _contextvars.Context()1002 1003        try:1004            # Start joinable thread1005            _start_joinable_thread(self._bootstrap, handle=self._os_thread_handle,1006                                   daemon=self.daemon)1007        except Exception:1008            with _active_limbo_lock:1009                del _limbo[self]1010            raise1011        self._started.wait()  # Will set ident and native_id1012 1013    def run(self):1014        """Method representing the thread's activity.1015 1016        You may override this method in a subclass. The standard run() method1017        invokes the callable object passed to the object's constructor as the1018        target argument, if any, with sequential and keyword arguments taken1019        from the args and kwargs arguments, respectively.1020 1021        """1022        try:1023            if self._target is not None:1024                self._target(*self._args, **self._kwargs)1025        finally:1026            # Avoid a refcycle if the thread is running a function with1027            # an argument that has a member that points to the thread.1028            del self._target, self._args, self._kwargs1029 1030    def _bootstrap(self):1031        # Wrapper around the real bootstrap code that ignores1032        # exceptions during interpreter cleanup.  Those typically1033        # happen when a daemon thread wakes up at an unfortunate1034        # moment, finds the world around it destroyed, and raises some1035        # random exception *** while trying to report the exception in1036        # _bootstrap_inner() below ***.  Those random exceptions1037        # don't help anybody, and they confuse users, so we suppress1038        # them.  We suppress them only when it appears that the world1039        # indeed has already been destroyed, so that exceptions in1040        # _bootstrap_inner() during normal business hours are properly1041        # reported.  Also, we only suppress them for daemonic threads;1042        # if a non-daemonic encounters this, something else is wrong.1043        try:1044            self._bootstrap_inner()1045        except:1046            if self._daemonic and _sys is None:1047                return1048            raise1049 1050    def _set_ident(self):1051        self._ident = get_ident()1052 1053    if _HAVE_THREAD_NATIVE_ID:1054        def _set_native_id(self):1055            self._native_id = get_native_id()1056 1057    def _set_os_name(self):1058        if _set_name is None or not self._name:1059            return1060        try:1061            _set_name(self._name)1062        except OSError:1063            pass1064 1065    def _bootstrap_inner(self):1066        try:1067            self._set_ident()1068            if _HAVE_THREAD_NATIVE_ID:1069                self._set_native_id()1070            self._set_os_name()1071            self._started.set()1072            with _active_limbo_lock:1073                _active[self._ident] = self1074                del _limbo[self]1075 1076            if _trace_hook:1077                _sys.settrace(_trace_hook)1078            if _profile_hook:1079                _sys.setprofile(_profile_hook)1080 1081            try:1082                self._context.run(self.run)1083            except:1084                self._invoke_excepthook(self)1085        finally:1086            self._delete()1087 1088    def _delete(self):1089        "Remove current thread from the dict of currently running threads."1090        with _active_limbo_lock:1091            del _active[get_ident()]1092            # There must not be any python code between the previous line1093            # and after the lock is released.  Otherwise a tracing function1094            # could try to acquire the lock again in the same thread, (in1095            # current_thread()), and would block.1096 1097    def join(self, timeout=None):1098        """Wait until the thread terminates.1099 1100        This blocks the calling thread until the thread whose join() method is1101        called terminates -- either normally or through an unhandled exception1102        or until the optional timeout occurs.1103 1104        When the timeout argument is present and not None, it should be a1105        floating-point number specifying a timeout for the operation in seconds1106        (or fractions thereof). As join() always returns None, you must call1107        is_alive() after join() to decide whether a timeout happened -- if the1108        thread is still alive, the join() call timed out.1109 1110        When the timeout argument is not present or None, the operation will1111        block until the thread terminates.1112 1113        A thread can be join()ed many times.1114 1115        join() raises a RuntimeError if an attempt is made to join the current1116        thread as that would cause a deadlock. It is also an error to join() a1117        thread before it has been started and attempts to do so raises the same1118        exception.1119 1120        """1121        if not self._initialized:1122            raise RuntimeError("Thread.__init__() not called")1123        if not self._started.is_set():1124            raise RuntimeError("cannot join thread before it is started")1125        if self is current_thread():1126            raise RuntimeError("cannot join current thread")1127 1128        # the behavior of a negative timeout isn't documented, but1129        # historically .join(timeout=x) for x<0 has acted as if timeout=01130        if timeout is not None:1131            timeout = max(timeout, 0)1132 1133        self._os_thread_handle.join(timeout)1134 1135    @property1136    def name(self):1137        """A string used for identification purposes only.1138 1139        It has no semantics. Multiple threads may be given the same name. The1140        initial name is set by the constructor.1141 1142        """1143        assert self._initialized, "Thread.__init__() not called"1144        return self._name1145 1146    @name.setter1147    def name(self, name):1148        assert self._initialized, "Thread.__init__() not called"1149        self._name = str(name)1150        if get_ident() == self._ident:1151            self._set_os_name()1152 1153    @property1154    def ident(self):1155        """Thread identifier of this thread or None if it has not been started.1156 1157        This is a nonzero integer. See the get_ident() function. Thread1158        identifiers may be recycled when a thread exits and another thread is1159        created. The identifier is available even after the thread has exited.1160 1161        """1162        assert self._initialized, "Thread.__init__() not called"1163        return self._ident1164 1165    if _HAVE_THREAD_NATIVE_ID:1166        @property1167        def native_id(self):1168            """Native integral thread ID of this thread, or None if it has not been started.1169 1170            This is a non-negative integer. See the get_native_id() function.1171            This represents the Thread ID as reported by the kernel.1172 1173            """1174            assert self._initialized, "Thread.__init__() not called"1175            return self._native_id1176 1177    def is_alive(self):1178        """Return whether the thread is alive.1179 1180        This method returns True just before the run() method starts until just1181        after the run() method terminates. See also the module function1182        enumerate().1183 1184        """1185        assert self._initialized, "Thread.__init__() not called"1186        return self._started.is_set() and not self._os_thread_handle.is_done()1187 1188    @property1189    def daemon(self):1190        """A boolean value indicating whether this thread is a daemon thread.1191 1192        This must be set before start() is called, otherwise RuntimeError is1193        raised. Its initial value is inherited from the creating thread; the1194        main thread is not a daemon thread and therefore all threads created in1195        the main thread default to daemon = False.1196 1197        The entire Python program exits when only daemon threads are left.1198 1199        """1200        assert self._initialized, "Thread.__init__() not called"

Showing the first 1,200 of 1643 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai