- №34 Потоки и многопоточность / для начинающих
- Что такое поток?
- Функции threading в Python
- threading.active_count()
- threading.current_thread()
- Модуль threading в Python
- Что такое поток в Python?
- Потоки в Python
- Функции threading
- threading.active_count()
- threading.current_thread()
- threading.main_thread()
- threading.enumerate()
- threading.Timer()
- Многопоточность в Python
- Как определять, сколько максимально потоков можно запускать?
№34 Потоки и многопоточность / для начинающих
Модуль threading в Python используется для реализации многопоточности в программах. В этом материале разберемся с Thread и разными функциями этого модуля.
Что такое поток?
В информатике поток — это минимальная единица работы, запланированная для выполнения операционной системой.
О потоках нужно знать следующее:
- Они существуют внутри процесса;
- В одном процессе может быть несколько потоков;
- Потоки в одном процессе разделяют состояние и память родительского процесса.
Модуль threading в Python можно представить таким простым примером:
import time
from threading import Thread
def sleepMe(i):
print("Поток %i засыпает на 5 секунд.\n" % i)
time.sleep(5)
print("Поток %i сейчас проснулся.\n" % i)
for i in range(10):
th = Thread(target=sleepMe, args=(i, ))
th.start()После запуска скрипта вывод будет следующий:
Поток 0 засыпает на 5 секунд. Поток 3 засыпает на 5 секунд. Поток 1 засыпает на 5 секунд. Поток 4 засыпает на 5 секунд. Поток 2 засыпает на 5 секунд. Поток 5 засыпает на 5 секунд. Поток 6 засыпает на 5 секунд. Поток 7 засыпает на 5 секунд. Поток 8 засыпает на 5 секунд. Поток 9 засыпает на 5 секунд. Поток 0 сейчас проснулся. Поток 3 сейчас проснулся. Поток 1 сейчас проснулся. Поток 4 сейчас проснулся. Поток 2 сейчас проснулся. Поток 5 сейчас проснулся. Поток 6 сейчас проснулся. Поток 7 сейчас проснулся. Поток 8 сейчас проснулся. Поток 9 сейчас проснулся.
У вас он может отличаться, потому что у параллельных потоков нет определенного порядка.
Функции threading в Python
Возьмем программу из первого примера и воспользуемся ею для демонстрации разных функций модуля.
threading.active_count()
Эта функция возвращает количество исполняемых на текущий момент потоков. Изменим последнюю программу, чтобы она выглядела вот так:
import time
import threading
from threading import Thread
def sleepMe(i):
print("Поток %i засыпает на 5 секунд." % i)
time.sleep(5)
print("Поток %i сейчас проснулся." % i)
for i in range(10):
th = Thread(target=sleepMe, args=(i, ))
th.start()
print("Запущено потоков: %i." % threading.active_count())Теперь в выводе будет показываться количество активных на текущий момент потоков:
Поток 0 засыпает на 5 секунд.Запущено потоков: 3. Запущено потоков: 4.Поток 1 засыпает на 5 секунд. Запущено потоков: 5.Поток 2 засыпает на 5 секунд. Поток 3 засыпает на 5 секунд.Запущено потоков: 6. Запущено потоков: 7.Поток 4 засыпает на 5 секунд. Поток 5 засыпает на 5 секунд.Запущено потоков: 8. Поток 6 засыпает на 5 секунд.Запущено потоков: 9. Запущено потоков: 10.Поток 7 засыпает на 5 секунд. Поток 8 засыпает на 5 секунд.Запущено потоков: 11. Поток 9 засыпает на 5 секунд.Запущено потоков: 12. Поток 0 сейчас проснулся. Поток 1 сейчас проснулся. Поток 2 сейчас проснулся. Поток 3 сейчас проснулся. Поток 4 сейчас проснулся. Поток 5 сейчас проснулся. Поток 6 сейчас проснулся. Поток 7 сейчас проснулся. Поток 8 сейчас проснулся. Поток 9 сейчас проснулся.
Также обратите внимание, что после запуска всех потоков счетчик показывает число 11, а не 10. Причина в том, что основной поток также учитывается наравне с 10 остальными.
threading.current_thread()
Эта функция возвращает исполняемый прямо сейчас поток. С ее помощью можно выполнять определенные действия с ним. Поменяем все тот же скрипт:
Модуль threading в Python
Модуль threading используется для реализации многопоточности в программах на Python. В этом уроке мы изучим Thread и различные функции модуля.
Что такое поток в Python?
Поток в Python — это наименьшая единица работы, которую планирует выполнять операционная система.
Некоторые моменты, которые следует учитывать при использовании потоков:
- Потоки существуют внутри процесса.
- В одном процессе может существовать несколько потоков.
- Потоки в одном процессе разделяют состояние и память родительского процесса.
Потоки в Python
Давайте представим модуль threading в Python на простом примере:
import time from threading import Thread def sleepMe(i): print("Thread %i going to sleep for 5 seconds." % i) time.sleep(5) print("Thread %i is awake now." % i) for i in range(10): th = Thread(target=sleepMe, args=(i, )) th.start()
Когда вы запускаете эту программу, результат может отличаться, поскольку параллельные потоки не имеют определенного порядка.
Функции threading
Мы повторно воспользуемся последней простой программой, которую мы написали с модулем пthreading, и создадим программу, чтобы показать различные функции данного модуля.
threading.active_count()
Эта функция возвращает количество выполняемых в данный момент потоков. Давайте изменим функцию sleepMe (…) последнего скрипта. Наш новый скрипт будет выглядеть так:
import time import threading from threading import Thread def sleepMe(i): print("Thread %i going to sleep for 5 seconds." % i) time.sleep(5) print("Thread %i is awake now." % i) for i in range(10): th = Thread(target=sleepMe, args=(i, )) th.start() print("Current Thread count: %i." % threading.active_count())
Обратите внимание, что количество активных потоков после того, как были запущены все 10 потоков, равно не 10, а 11. Это связано с тем, что он также считает, что основной поток внутри из других 10 потоков был создан.
threading.current_thread()
Эта функция возвращает текущий исполняемый поток. Используя этот метод, мы можем выполнять определенные действия с полученным потоком. Давайте изменим наш скрипт, чтобы использовать этот метод сейчас:
import time import threading from threading import Thread def sleepMe(i): print("Thread %s going to sleep for 5 seconds." % threading.current_thread()) time.sleep(5) print("Thread %s is awake now.\n" % threading.current_thread()) #Creating only four threads for now for i in range(4): th = Thread(target=sleepMe, args=(i, )) th.start()
threading.main_thread()
Эта функция возвращает основной поток этой программы. Из этого потока можно создать больше потоков. Давайте посмотрим на этот сценарий:
import threading print(threading.main_thread())
Как показано на изображении, стоит отметить, что функция main_thread() была введена только в Python 3. Поэтому будьте осторожны, чтобы использовать эту функцию только при использовании версий Python 3+.
threading.enumerate()
Эта функция возвращает список всех активных потоков. Давайте напишем пример, чтобы использовать его:
import threading for thread in threading.enumerate(): print("Thread name is %s." % thread.getName())
Когда мы выполняли этот скрипт, у нас был только основной поток, отсюда и результат.
threading.Timer()
Эта функция модуля потоковой передачи используется для создания нового потока и сообщения ему о том, что он должен запускаться только через определенное время. После запуска он должен вызвать указанную функцию. Изучим это на примере:
import threading def delayed(): print("I am printed after 5 seconds!") thread = threading.Timer(3, delayed) thread.start()
Многопоточность в Python
В этом посте мы увидели некоторые функции модуля threading в Python и то, как он предоставляет удобные методы для управления потоками в многопоточной среде.
Как определять, сколько максимально потоков можно запускать?
Здравствуйте. Есть класс. Он накапливает в себе задания на отправку запросов, а потом разом, многопоточно их отправляет. Как определять, сколько максимально потоков можно запускать? На домашнем ноутбуке ставлю 100 потоков и на каждый выскакиевает ошибка TimeoutError, ставлю по 10, более менее работает, ставлю по 3 потока, работает без ошибок TimeoutError. Подскажите в какую сторону искать, мануалы по threading молчат об этом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
from queue import Queue from threading import Thread import requests class Requester: def __init__(self): self.taskList = [] self.num_worker_threads = 10 def __call__(self, url, session): self.taskList.append([url, session]) def request(self): queue = Queue() resultList = [] for task in self.taskList: queue.put(task) def do_work(task): # Выполняем запросы try: url, session = task r = session.get(url, timeout=15) resultList.append(r) except requests.exceptions.Timeout: queue.put(task) def worker(queue): while True: task = queue.get() do_work(task) queue.task_done() for i in range(self.num_worker_threads): t = Thread(target=worker, args=(queue,)) t.setDaemon(True) t.start() queue.join() return resultList