← Назад к вопросам

Какие знаешь способы конкурентного выполнения программ в Python?

1.8 Middle🔥 121 комментариев
#Python#Фреймворки тестирования

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основные способы конкурентного выполнения в Python

В Python существует несколько подходов для организации конкурентного (concurrent) выполнения кода, которые можно разделить на три основные категории: многопоточность, многопроцессность и асинхронное программирование. Выбор конкретного метода зависит от типа задачи (I/O-bound или CPU-bound) и требований к производительности.

1. Многопоточность (Threading)

Многопоточность использует потоки (threads) в рамках одного процесса. В Python из-за Global Interpreter Lock (GIL) потоки не выполняются действительно параллельно на многопроцессорных системах, но эффективны для I/O-операций.

Ключевые особенности:

  • Потоки разделяют общее пространство памяти
  • Подходят для задач, связанных с ожиданием (сеть, дисковый ввод-вывод)
  • GIL ограничивает параллельное выполнение CPU-intensive задач

Пример использования threading:

import threading
import time

def worker(task_id):
    print(f"Начало задачи {task_id}")
    time.sleep(2)  # Имитация I/O-операции
    print(f"Завершение задачи {task_id}")

threads = []
for i in range(3):
    thread = threading.Thread(target=worker, args=(i,))
    threads.append(thread)
    thread.start()

for thread in threads:
    thread.join()

print("Все задачи завершены")

2. Многопроцессность (Multiprocessing)

Многопроцессность создает отдельные процессы с собственным интерпретатором Python и памятью, что позволяет обойти ограничения GIL и использовать несколько ядер CPU.

Ключевые особенности:

  • Каждый процесс имеет независимое пространство памяти
  • Подходит для CPU-intensive задач (вычисления, обработка данных)
  • Более высокие накладные расходы на создание и межпроцессное взаимодействие

Пример использования multiprocessing:

import multiprocessing
import time

def cpu_intensive_task(n):
    result = sum(i * i for i in range(n))
    return result

if __name__ == "__main__":
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(cpu_intensive_task, [1000000, 2000000, 3000000, 4000000])
        print(f"Результаты: {results}")

3. Асинхронное программирование (Asyncio)

Асинхронный подход использует корутины (coroutines) и цикл событий (event loop) для неблокирующего выполнения I/O-операций.

Ключевые особенности:

  • Однопоточная модель с кооперативной многозадачностью
  • Идеально для высоконагруженных I/O-приложений (веб-серверы, клиенты)
  • Низкие накладные расходы по сравнению с потоками

Пример использования asyncio:

import asyncio
import aiohttp

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        'https://example.com',
        'https://python.org',
        'https://github.com'
    ]
    
    async with aiohttp.ClientSession() as session:
        tasks = [fetch_url(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        for url, content in zip(urls, results):
            print(f"{url}: {len(content)} символов")

asyncio.run(main())

4. Concurrent.futures (универсальный API)

Библиотека concurrent.futures предоставляет высокоуровневый интерфейс для асинхронного выполнения через пулы потоков и процессов.

Преимущества:

  • Единый API для потоков и процессов
  • Использование Future объектов для отложенных результатов
  • Упрощенное управление конкурентным выполнением

Пример использования ThreadPoolExecutor и ProcessPoolExecutor:

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import time

def io_bound_task(x):
    time.sleep(1)
    return x * x

def cpu_bound_task(x):
    return sum(i * i for i in range(x))

# Для I/O-задач
with ThreadPoolExecutor(max_workers=5) as executor:
    results = list(executor.map(io_bound_task, range(5)))
    print(f"I/O результаты: {results}")

# Для CPU-задач
with ProcessPoolExecutor(max_workers=4) as executor:
    results = list(executor.map(cpu_bound_task, [100000, 200000, 300000]))
    print(f"CPU результаты: {results}")

Сравнительный анализ подходов

КритерийThreadingMultiprocessingAsyncio
ПараллелизмПсевдопараллелизм (из-за GIL)Истинный параллелизмКооперативная многозадачность
ПамятьОбщая памятьРаздельная памятьОбщая память
Накладные расходыНизкиеВысокиеОчень низкие
Идеальные сценарииI/O-bound задачиCPU-bound задачиВысокочастотные I/O-операции
Сложность отладкиСредняяВысокаяВысокая

Рекомендации по выбору подхода

  1. Для сетевых операций и работы с файлами (I/O-bound) используйте asyncio для максимальной производительности или threading для более простых сценариев.

  2. Для вычислительных задач (CPU-bound) выбирайте multiprocessing для использования нескольких ядер процессора.

  3. Для смешанных нагрузок рассмотрите комбинированные подходы, например, процессы для вычислений и потоки/асинхронность для I/O внутри каждого процесса.

  4. Для задач с регулярным паттерном используйте concurrent.futures как наиболее универсальное решение с чистым API.

На практике часто встречаются гибридные подходы, где основной процесс использует несколько подпроцессов для вычислений, каждый из которых внутри использует асинхронные операции для эффективной работы с I/O. Современные фреймворки типа FastAPI успешно комбинируют эти подходы для достижения максимальной производительности веб-приложений.

Какие знаешь способы конкурентного выполнения программ в Python? | PrepBro