В разделе рассмотрены функции модуля threading
, при помощи которых можно узнать общие сведения о потоках, запущенных в программе.
threading.active_count()
количество живых потоков,threading.current_thread()
текущий поток,threading.excepthook()
обрабатывает неперехваченные исключения в потоках,threading.get_ident()
идентификатор текущего потока,threading.get_native_id()
интегральный идентификатор текущего потока,threading.enumerate()
список объектов всех живых потоков,threading.main_thread()
объект основной потока,threading.TIMEOUT_MAX
максимально значение для тайм-аута блокировки.threading.active_count()
:Функция threading.active_count()
возвращает количество живых потоков - объектов threading.Thread()
. Возвращенное количество равно длине списка, возвращаемого функцией threading.enumerate()
.
import threading, time def worker(): time.sleep(1) for _ in range(6): thread = threading.Thread(target=worker) thread.start() # использование 'threading.active_count()' # 7 потоков = 6 порожденных + 1 основной n_thread = threading.active_count() print(n_thread) # 7
threading.current_thread()
:Функция threading.current_thread()
возвращает текущий поток - объект threading.Thread()
, соответствующий потоку управления вызывающего объекта.
Если поток управления вызывающего объекта не был создан через модуль потоковой передачи, то возвращается фиктивный объект потока с ограниченной функциональностью.
import threading, time, logging def worker(): # использование 'threading.current_thread()' # получаем экземпляр Thread и атрибутом # .name извлекаем имя потока thread_name = threading.current_thread().name logging.debug(f'Starting {thread_name}') time.sleep(1) logging.basicConfig( level=logging.DEBUG, format='[%(levelname)s] %(message)s', ) th1 = threading.Thread(target=worker) th1.start() th2 = threading.Thread(name='worker', target=worker) th2.start() # [DEBUG] Starting Thread-1 # [DEBUG] Starting worker
threading.excepthook(args, /)
:Функция threading.excepthook()
обрабатывает неперехваченные исключения, вызванные в методе Thread.run()
.
Аргумент args имеет следующие атрибуты:
exc_type
: Тип исключения.exc_value
: Значение исключения, может быть None
.exc_traceback
: Трассировка исключения, может быть None
.thread
: Поток, который вызвал исключение, может быть None
.Если аргумент exc_type
это SystemExit
, то исключение игнорируется. В противном случае исключение выводится в sys.stderr
.
Если функция threading.excepthook()
вызывает исключение, то для его обработки вызывается sys.excepthook()
.
Функцию threading.excepthook()
можно переопределить, чтобы контролировать, как обрабатываются неперехваченные исключения, вызванные методом Thread.run()
.
Сохранение аргумента exc_value
с использованием пользовательского хука может создать ссылочный цикл. Его следует явно очистить, когда исключение больше не требуется.
Сохранение потока с использованием пользовательского хука может воскресить его, если он установлен на финализируемый объект. Чтобы избежать воскрешения объектов, избегайте сохранения потока после завершения пользовательского хука.
Смотрите также функцию sys.excepthook()
, которая обрабатывает неперехваченные исключения в однопоточных программах.
Новое в Python 3.8.
threading.get_ident()
:Функция threading.get_ident()
возвращает идентификатор текущего потока. Это ненулевое целое число.
Возвращаемое число не имеет прямого значения. Оно предназначено для использования в качестве "волшебного" файла cookie
, например для индексации словаря данных, специфичных для потока.
Идентификаторы потока могут быть повторно использованы при выходе из потока и создании другого потока.
import threading, time, logging def worker(): name = threading.current_thread().name # использование 'threading.get_ident()' ident = threading.get_ident() # тоже самое можно получить через атрибут ident = threading.ident logging.debug(f'Starting {name}, id: {ident}') time.sleep(1) logging.basicConfig( level=logging.DEBUG, format='[%(levelname)s] %(message)s', ) for _ in range(3): thread = threading.Thread(target=worker) thread.start() # [DEBUG] Starting Thread-1, id: 140190611068672 # [DEBUG] Starting Thread-2, id: 140190602675968 # [DEBUG] Starting Thread-3, id: 140190594283264
threading.get_native_id()
:Функция threading.get_native_id()
возвращает собственный интегральный идентификатор текущего потока, назначенный ядром. Это неотрицательное целое число.
Его значение может использоваться для уникальной идентификации этого конкретного потока в масштабах всей системы до тех пор, пока поток не завершится, после чего это значение может быть переработано ОС.
Пример получения собственного интегрального идентификатора такой же как у threading.get_ident()
Доступность: Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX.
Новое в Python 3.8.
threading.enumerate()
:Функция threading.enumerate()
возвращает список объектов threading.Thread()
всех живых потоков.
В список входят демонические потоки и объекты фиктивного потока плюс основной поток. В этот список не входят завершенные потоки и потоки, которые еще не были запущены.
import threading, time, logging def worker(): time.sleep(1) logging.basicConfig( level=logging.DEBUG, format='[%(levelname)s] %(message)s', ) for _ in range(3): thread = threading.Thread(target=worker) thread.start() # использование 'threading.enumerate()' # проходимся по экземплярам 'Thread' # и из которых атрибутом '.name' # извлекаем имена живых потоков for t in threading.enumerate(): logging.debug(f'Thread Name: {t.name}') # [DEBUG] Thread Name: MainThread # [DEBUG] Thread Name: Thread-1 # [DEBUG] Thread Name: Thread-2 # [DEBUG] Thread Name: Thread-3
threading.main_thread()
:Функция threading.main_thread()
возвращает объект основной потока.
В нормальных условиях основным потоком является поток, из которого был запущен интерпретатор Python.
import threading, time, logging def worker(): name = threading.current_thread().name time.sleep(1) logging.debug(f'Ending {name}') logging.basicConfig( level=logging.DEBUG, format='[%(levelname)s] %(message)s', ) # использование 'threading.main_thread()' # получаем экземпляр основного потока main_thread = threading.main_thread() # получаем имя основного потока main_thread_name = main_thread.name logging.debug(f'{main_thread_name} starting...') for _ in range(3): thread = threading.Thread(target=worker) thread.start() for t in threading.enumerate(): # Список 'threading.enumerate()' включает в себя основной # поток и т.к. присоединение основного потока самого к себе # приводит к тупиковой ситуации, то его необходимо пропустить if t is main_thread: continue thead_name = t.name logging.debug(f'{main_thread_name} joining {thead_name}') t.join() # [DEBUG] MainThread starting... # [DEBUG] MainThread joining Thread-1 # [DEBUG] Ending Thread-1 # [DEBUG] MainThread joining Thread-2 # [DEBUG] Ending Thread-3 # [DEBUG] Ending Thread-2 # [DEBUG] MainThread joining Thread-3
threading.TIMEOUT_MAX
:Константа threading.TIMEOUT_MAX
представляет собой максимально допустимое значение для параметра тайм-аута функция блокировки (Lock.acquire()
, RLock.acquire()
, Condition.wait()
, и т. д.).
Указание времени ожидания, превышающее это значение будет вызывать исключение OverflowError
.
>>> import threading >>> threading.TIMEOUT_MAX # 9223372036.0