Поиск данных не должен быть работой одного человека
Многие проекты требуют определенной формы сбора данных, что влечет за собой получение информации из внешних источников, таких как базы данных и веб-сайты.
К сожалению, процедуры сбора данных могут стать утомительными и трудоемкими по мере увеличения количества задач по извлечению данных.
К счастью, пользователи могут избавить себя от длительного времени выполнения, включив многопоточность при выполнении извлечения данных.
Здесь мы выделяем преимущества многопоточности и обсуждаем, как ее можно включить в программы для ускорения операций сбора данных в Python.
Почему многопоточность?
Многопоточность позволяет пользователям выполнять операции быстрее за счет одновременного запуска различных частей процесса (известных как потоки).
Рассмотрим следующую функцию, выполнение которой занимает около пяти секунд.

Если для выполнения функции требуется пять секунд, сколько времени потребуется, чтобы запустить ее три раза?

Это не проблема. На всю операцию потребуется около 15 секунд.
Однако такое расположение может быть невыносимо неэффективным при большом количестве задач. Насколько громоздким был бы этот подход, если бы функцию приходилось повторять сотни или тысячи раз?
К счастью, если интересующие задачи не зависят друг от друга, пользователи могут сократить время, необходимое для выполнения операции, за счет использования многопоточности, которая распределяет задачи по нескольким потокам.
Многопоточность в Python
Python позволяет пользователям включать многопоточность с пакетом concurrent.futures, который предлагает класс ThreadPoolExecutor.
Одной из самых мощных функций этого класса является метод map, который, как и встроенный метод map, сопоставляет интересующую функцию с заданным набором аргументов.
Мы можем использовать этот класс для ускорения предыдущей операции, выполняя задачи одновременно в нескольких потоках.

Вместо того, чтобы выполнять задачи по одной, ThreadPoolExecutor выполняет несколько задач за один и тот же период времени, тем самым значительно сокращая время выполнения.
Многопоточность для сбора данных
Многопоточность подходит для задач, связанных с вводом-выводом, которые тратят много времени на взаимодействие с той или иной формой внешней системы, такой как база данных или веб-сервер. Поскольку процедуры сбора данных часто предполагают получение данных из внешнего источника, целесообразно улучшить такие процессы с помощью многопоточности.
Многопоточность обычно используется для выполнения таких операций, как удаление данных с веб-сайтов, чтение файлов или выполнение вызовов с помощью API с гораздо большей эффективностью.
В качестве простого примера предположим, что мы собираем данные с помощью API университетских доменов и имен, который предоставляет информацию об университетах в данной стране.
Используя следующую функцию, можно получить данные о названиях университетов любой страны.
Цель состоит в том, чтобы получить информацию об университетах из 248 разных стран. Без многопоточности эту функцию можно использовать для сбора данных об университетах для одной страны за раз с помощью простого цикла.

Сбор данных по всем странам таким образом занимает около 14 секунд. Хотя этот подход выполняет свою работу, он крайне неэффективен.
Давайте посмотрим, сколько времени уходит на получение одних и тех же данных при выполнении функции в десяти потоках с классом ThreadPoolExecutor.

Выполнение извлечения данных с помощью API одновременно за счет использования многопоточности значительно сокращает время.
Ограничения
Хотя вы, возможно, оцениваете многопоточность с точки зрения ее способности сокращать время выполнения процедур сбора данных, у вас может возникнуть вопрос: зачем ограничиваться ее использованием только для сбора данных? Почему бы нам не использовать многопоточность для ускорения каждой интересующей нас операции?
Проще говоря, у этой техники есть свои ограничения.
Хотя многопоточность подходит для задач, связанных с вводом-выводом, она неадекватна, когда речь идет о задачах, связанных с процессором. Задачи, связанные с ЦП, в первую очередь зависят от вычислительной мощности ЦП.
Включение многопоточности в такие операции может оказаться неэффективным и даже увеличить время выполнения.
Таким образом, если вы имеете дело с ресурсоемкими процессами, такими как обучение моделей машинного обучения или обработка изображений, многопоточность не является подходящим решением. В таких случаях рассмотрите возможность изучения более жизнеспособных альтернатив, таких как многопроцессорность.
Заключение
Многопоточность — бесценный ресурс для сбора данных.
При этом эта статья в основном служит для пропаганды использования этой техники и не слишком углубляется в лучшие модули Python для выполнения многопоточности.
Лично я предпочитаю использовать класс ThreadPoolExecutor из пакета concurrent.futures из-за его простого интерфейса. Однако есть и другие варианты, которые можно использовать для реализации многопоточности (например, модуль threading).
Не стесняйтесь исследовать различные методы включения многопоточности в Python и экспериментировать с ними, чтобы увидеть, какие из них подходят вам лучше всего.
Удачного кодирования!