Порівняння Threading, Multiprocessing та Asyncio + Приклад застосування

Автор Tuvze, ер. 30, 2026, 02:20 PM

« попередня та - наступна тема »

Tuvze

У Python concurrency (паралелізм) може значно підвищити продуктивність в I/O-інтенсивних або CPU-інтенсивних завданнях. Однак через обмеження GIL (Global Interpreter Lock) у Python важливо вибрати правильний підхід. У цій статті ми порівняємо підходи threading, multiprocessing та asyncio і покажемо сценарії, де кожен з них є найбільш підходящим, з реальним прикладом застосування.

1. Threading (Потоки)
  • Підходить для I/O-bound завдань (мережеві запити, читання/запис файлів).
  • Через GIL не забезпечує справжній паралелізм у CPU-bound завданнях.
  • Легкі та швидко запускаються.

Основний приклад:
import threading
import time

def dosya_indir(url):
    print(f"Шу url завантажується...")
    time.sleep(2)  # Симуляція мережевого запиту
    print(f"Шу url завершено.")

urls = ["site1.com", "site2.com", "site3.com", "site4.com"]
threads = []
for url in urls:
    t = threading.Thread(target=dosya_indir, args=(url,))
    threads.append(t)
    t.start()
for t in threads:
    t.join()
print("Усі завантаження завершено.")

2. Multiprocessing (Багатопроцесність)
  • Забезпечує справжній паралелізм для CPU-bound завдань (GIL не впливає).
  • Кожен процес використовує окремий простір пам'яті → більше споживання пам'яті.
  • Для обміну даними потрібні структури, такі як Queue, Pipe, Manager.

Приклад CPU-інтенсивного завдання:
from multiprocessing import Process, cpu_count
import time

def hesapla(n):
    toplam = 0
    for i in range(n):
        toplam += i ** 2
    print(f" {n} для результату: {toplam}")

if __name__ == "__main__":
    sayilar = [10_000_000] * cpu_count()
    processes = []
    for sayi in sayilar:
        p = Process(target=hesapla, args=(sayi,))
        processes.append(p)
        p.start()
    for p in processes:
        p.join()
    print("Усі обчислення завершено.")

3. Asyncio (Асинхронне програмування)
  • Сучасний і найпотужніший підхід (особливо в Python 3.7+).
  • Керує тисячами паралельних завдань в одному потоці.
  • Найефективніший метод для I/O-bound завдань (мережа, бази даних, виклики API).

Реалістичний приклад asyncio: Паралельне отримання даних з кількох API.
import asyncio
import aiohttp
import time

async def api_cagir(session, url):
    async with session.get(url) as response:
        data = await response.json()
        print(f"{url} -> {len(data)} елементів отримано")
        return data

async def ana():
    urls = [
        "https://jsonplaceholder.typicode.com/posts",
        "https://jsonplaceholder.typicode.com/comments",
        "https://jsonplaceholder.typicode.com/albums",
        "https://jsonplaceholder.typicode.com/photos"
    ]
    async with aiohttp.ClientSession() as session:
        gorevler = [api_cagir(session, url) for url in urls]
        sonuclar = await asyncio.gather(*gorevler)
        print(f"Всього {sum(len(s) for s in sonuclar)} елементів зібрано")

if __name__ == "__main__":
    basla = time.time()
    asyncio.run(ana())
    print(f"Загальний час: {time.time() - basla:.2f} секунд")

Який підхід використовувати коли? (Порівняння)
  • Найкраще використання: Для threading - I/O-bound; для multiprocessing - CPU-bound; для asyncio - I/O-bound (високий обсяг).
  • Справжній паралелізм: Для threading - Ні (GIL); для multiprocessing - Так; для asyncio - Ні (один потік).
  • Споживання пам'яті: Для threading - Низьке; для multiprocessing - Високе; для asyncio - Дуже низьке.
  • Вартість запуску: Для threading - Низька; для multiprocessing - Висока; для asyncio - Дуже низька.
  • Складність коду: Для threading - Середня; для multiprocessing - Висока; для asyncio - Середня-Висока.
  • Найпопулярніші бібліотеки: Для threading - requests + ThreadPoolExecutor; для multiprocessing - concurrent.futures; для asyncio - aiohttp, httpx, aiomysql.

Практичні рекомендації
  • Для невеликих-середніх I/O-завдань → asyncio (стандарт майбутнього).
  • Для важкої математики/обчислень → multiprocessing або concurrent.futures.ProcessPoolExecutor.
  • Для простих скриптів і швидких рішень → threading + ThreadPoolExecutor.

У нашому форумі ви можете поділитися своїми проектами concurrency, обговорити, який метод найкраще підходить для вашого сценарію використання.