Ответ
В Python есть три основных подхода для конкурентного и параллельного выполнения кода, каждый из которых решает свой класс задач.
-
Многопоточность (
threading) Используется для конкурентного выполнения задач, ограниченных вводом-выводом (I/O-bound), таких как сетевые запросы или чтение с диска. Из-за Global Interpreter Lock (GIL) потоки в CPython не могут выполняться параллельно на нескольких ядрах CPU, но могут эффективно переключаться между собой во время ожидания I/O.import threading import time def network_request(url): print(f"Fetching {url}...") time.sleep(1) # Имитация ожидания ответа от сети print(f"Finished {url}") threads = [ threading.Thread(target=network_request, args=(f"site.com/{i}",)) for i in range(3) ] for t in threads: t.start() for t in threads: t.join() -
Многопроцессорность (
multiprocessing) Обеспечивает истинный параллелизм, запуская задачи в отдельных процессах, каждый со своим интерпретатором Python и памятью. Это позволяет обойти GIL и полностью утилизировать все ядра CPU.Почему это полезно? Идеально для задач, ограниченных производительностью процессора (CPU-bound), например, математические вычисления, обработка изображений.
from multiprocessing import Process def cpu_heavy_task(n): result = sum(i * i for i in range(n)) print(f"Task finished with result: {result}") processes = [ Process(target=cpu_heavy_task, args=(10**7,)) for _ in range(3) ] for p in processes: p.start() for p in processes: p.join() -
Асинхронность (
asyncio) Современный подход для конкурентного выполнения большого количества I/O-bound задач в одном потоке с помощью событийного цикла (event loop). Код пишется с использованием синтаксисаasync/await.Почему это полезно? Очень эффективно для приложений с десятками тысяч одновременных сетевых соединений (веб-серверы, боты, парсеры).
import asyncio async def network_request_async(url): print(f"Fetching {url}...") await asyncio.sleep(1) # Неблокирующее ожидание print(f"Finished {url}") async def main(): tasks = [network_request_async(f"site.com/{i}") for i in range(3)] await asyncio.gather(*tasks) asyncio.run(main())
Ключевой фактор выбора:
- I/O-bound:
threadingилиasyncio. - CPU-bound:
multiprocessing.