Уроки програмного забезпечення | Tuvze.com
Підручники з програмного забезпечення => Python => Тема розпочата: Tuvze від ер. 30, 2026, 02:20 PM
У 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, обговорити, який метод найкраще підходить для вашого сценарію використання.