Многопоточность значительно сокращает время выполнения программы. Узнайте, как реализовать многопоточность в Python.

Время выполнения является одним из распространенных показателей эффективности программы. Чем быстрее время выполнения, тем лучше программа. Многопоточность — это метод, который позволяет программе выполнять несколько задач или процессов одновременно.

Вы узнаете, как использовать встроенный в Python резьба модуль и concurrent.features модуль. Оба этих модуля предлагают простые способы создания потоков и управления ими.

Важность потоковой передачи

Потоки сокращают время, необходимое программе для выполнения задания. Если задание содержит несколько независимых задач, вы можете использовать многопоточность для одновременного выполнения задач, уменьшая время ожидания программы для завершения одной задачи перед переходом к следующей.

Например, программа, которая загружает несколько файлов изображений из Интернета. Эта программа может использовать многопоточность для загрузки файлов параллельно, а не по одному. Это устраняет время, которое программа должна была бы ждать завершения процесса загрузки одного файла, прежде чем перейти к следующему.

instagram viewer

Начальная программа перед нарезкой

Функция в следующей программе представляет задачу. Задача состоит в том, чтобы приостановить выполнение программы на одну секунду. Программа дважды вызывает функцию, создавая две задачи. Затем он вычисляет время, необходимое для запуска всей программы, и затем отображает его на экране.

Импортировать время

start_time = время.perf_counter()

дефПауза():
Распечатать("Спящая 1 секунда...")
время сна(1)
Распечатать(«Заснул...»)

Пауза()
Пауза()
Finish_time = time.perf_counter()
Распечатать(f'Завершено через {раунд (время_окончания - время_начала, 2)} секунда (с)')

Вывод показывает, что на выполнение программы ушло 2,01 секунды. Каждая задача занимала одну секунду, а выполнение остального кода занимало 0,01 секунды.

Вы можете использовать потоки для одновременного выполнения обеих задач. Для выполнения обеих задач потребуется одна секунда.

Реализация потоков с помощью модуля threading

Чтобы изменить исходный код для реализации многопоточности, импортируйте резьба модуль. Создайте две темы, thread_1 и thread_2 используя Нить сорт. Позвоните начинать метод в каждом потоке, чтобы начать его выполнение. Позвоните присоединиться метод в каждом потоке, чтобы дождаться завершения их выполнения, прежде чем остальная часть программы будет выполнена.

Импортировать время
Импортировать резьба
start_time = время.perf_counter()

дефПауза():
Распечатать("Спящая 1 секунда...")
время сна(1)
Распечатать(«Заснул...»)

thread_1 = многопоточность. Тема (цель=пауза)
thread_2 = многопоточность. Тема (цель=пауза)

thread_1.start()
thread_2.start()

thread_1.присоединиться()
thread_2.присоединиться()

Finish_time = time.perf_counter()
Распечатать(f'Завершено через {раунд (время_окончания - время_начала, 2)} секунда (с)')

Программа будет запускать оба потока одновременно. Это сократит время, необходимое для выполнения обеих задач.

Вывод показывает, что время, необходимое для выполнения одних и тех же задач, составляет около секунды. Это вдвое меньше времени, которое занимала первоначальная программа.

Реализация многопоточности с помощью модуля concurrent.futures

Python 3.2 увидел введение параллельные.фьючерсы модуль. Этот модуль предоставляет высокоуровневый интерфейс для выполнения асинхронных задач с использованием потоков. Это обеспечивает более простой способ выполнения задач параллельно.

Чтобы изменить исходную программу для использования многопоточности, импортируйте модуль concurrent.features. Использовать ThreadPoolExecutor class из модуля concurrent.futures для создания пула потоков. Отправить Пауза функцию в бассейн дважды. представлять на рассмотрение метод возвращает будущее объект, представляющий результат вызова функции.

Итерация по фьючерсы и распечатать их результаты, используя результат метод.

Импортировать время
Импортировать параллельные.фьючерсы

start_time = время.perf_counter()

дефПауза():
Распечатать("Спящая 1 секунда...")
время сна(1)
возвращаться«Заснул...»

с параллельные.фьючерсы. ThreadPoolExecutor() как исполнитель:
результаты = [executor.submit (пауза) для _ в диапазон(2)]
для ф в concurrent.futures.as_completed (результаты):
печать (f.результат())

Finish_time = time.perf_counter()

Распечатать(f'Завершено через {раунд (время_окончания - время_начала, 2)} секунда (с)')

Модуль concurrent.features позаботится о запуске потоков и присоединении к ним. Это делает ваш код чище.

Вывод идентичен выходу модуля threading. Модуль threading полезен для простых случаев, когда вам нужно запустить несколько потоков параллельно. С другой стороны, модуль concurrent.futures полезен для более сложных случаев, когда вам нужно одновременно запускать множество задач.

Использование многопоточности в реальном сценарии

Использование потоков для запуска вышеуказанной программы сократило время на одну секунду. В реальном мире потоки экономят больше времени. Создайте программу, которая загружает изображения из Интернета. Начать с создание новой виртуальной среды. Выполните следующую команду в терминале, чтобы установить Запросы библиотека:

запросы на установку pip

Библиотека запросов позволит вам отправлять HTTP-запросы. Импортируйте библиотеку запросов и библиотеку времени.

Импортировать Запросы
Импортировать время

Создайте список URL-адресов изображений, которые вы хотите загрузить. Пусть их будет хотя бы десять, чтобы можно было заметить существенную разницу при реализации многопоточности.

img_urls = [
' https://images.unsplash.com/photo-1524429656589-6633a470097c',
' https://images.unsplash.com/photo-1530224264768-7ff8c1789d79',
' https://images.unsplash.com/photo-1564135624576-c5c88640f235',
' https://images.unsplash.com/photo-1541698444083-023c97d3f4b6',
' https://images.unsplash.com/photo-1522364723953-452d3431c267',
' https://images.unsplash.com/photo-1513938709626-033611b8cc03',
' https://images.unsplash.com/photo-1507143550189-fed454f93097',
' https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e',
' https://images.unsplash.com/photo-1504198453319-5ce911bafcde',
' https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99',
' https://images.unsplash.com/photo-1516972810927-80185027ca84',
' https://images.unsplash.com/photo-1550439062-609e1531270e',
]

Перебрать список URL-адресов, загружающих каждое изображение в ту же папку, в которой находится ваш проект. Отобразите время, затраченное на загрузку изображений, вычитая время окончания из времени начала.

start_time = время.perf_counter()
для img_url в img_urls:
img_bytes = запросы.get (img_url).content
img_name = img_url.split('/')[3]
img_имя = ж'{img_name}.jpg'
с открыть (img_name, 'вб') как img_file:
img_file.write (img_bytes)
Распечатать(ж'{img_name} был скачан...')
Finish_time = time.perf_counter()
Распечатать(f'Завершено через {время_окончания - время_начала} секунды)

Программе требуется около 22 секунд, чтобы загрузить 12 изображений. Это может варьироваться для вас, так как время, необходимое для загрузки изображений, также зависит от скорости вашего интернета.

Измените программу, чтобы использовать многопоточность, используя модуль concurrent.features. Вместо цикла используйте функцию. Это функция, которую вы передадите исполнитель пример.

Импортировать Запросы
Импортировать время
Импортировать параллельные.фьючерсы

img_urls = [
' https://images.unsplash.com/photo-1524429656589-6633a470097c',
' https://images.unsplash.com/photo-1530224264768-7ff8c1789d79',
' https://images.unsplash.com/photo-1564135624576-c5c88640f235',
' https://images.unsplash.com/photo-1541698444083-023c97d3f4b6',
' https://images.unsplash.com/photo-1522364723953-452d3431c267',
' https://images.unsplash.com/photo-1513938709626-033611b8cc03',
' https://images.unsplash.com/photo-1507143550189-fed454f93097',
' https://images.unsplash.com/photo-1493976040374-85c8e12f0c0e',
' https://images.unsplash.com/photo-1504198453319-5ce911bafcde',
' https://images.unsplash.com/photo-1530122037265-a5f1f91d3b99',
' https://images.unsplash.com/photo-1516972810927-80185027ca84',
' https://images.unsplash.com/photo-1550439062-609e1531270e',
]

start_time = время.perf_counter()

дефdownload_image(img_url):
img_bytes = запросы.get (img_url).content
img_name = img_url.split('/')[3]
img_имя = ж'{img_name}.jpg'
с открыть (img_name, 'вб') как img_file:
img_file.write (img_bytes)
Распечатать(ж'{img_name} был скачан...')

с параллельные.фьючерсы. ThreadPoolExecutor() как исполнитель:
executor.map (download_image, img_urls)

Finish_time = time.perf_counter()

Распечатать(f'Завершено через {finish_time-start_time} секунды)

После введения резьбы. Время значительно сокращается. На выполнение программы ушло всего 4 секунды.

Сценарии, подходящие для потоковой передачи

Вот некоторые из сценариев, подходящих для потоковой передачи:

  • Задачи, связанные с вводом-выводом: если программа проводит большую часть времени в ожидании завершения операций ввода или вывода. Многопоточность может повысить производительность, позволяя другим задачам выполняться во время ожидания завершения операций ввода-вывода.
  • Веб-скрапинг: Веб-скрапинг включает в себя выполнение HTTP-запросов и анализ HTML-ответов.. Многопоточность помогает ускорить процесс, позволяя выполнять несколько запросов одновременно.
  • Задачи, связанные с процессором: многопоточность может помочь повысить производительность за счет параллельного выполнения нескольких задач.

Ознакомьтесь с многопоточностью на других языках

Python — не единственный язык, поддерживающий многопоточность. Большинство языков программирования поддерживают те или иные формы многопоточности. Важно ознакомиться с реализацией потоков на других языках. Это дает вам необходимые навыки для работы с различными сценариями, в которых может применяться многопоточность.