Какие знаешь библиотеки для работы с многопоточностью

Ответ

В Python для работы с многопоточностью чаще всего используют:

  1. threading — стандартная библиотека для создания и управления потоками. Из-за GIL подходит для I/O-bound задач, но не для CPU-bound.
import threading

def task():
    print("Thread running")

thread = threading.Thread(target=task)
thread.start()
thread.join()
  1. concurrent.futures — высокоуровневый интерфейс для пула потоков (ThreadPoolExecutor) или процессов (ProcessPoolExecutor).
from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor() as executor:
    executor.submit(lambda: print("Task executed"))
  1. asyncio — для асинхронного I/O (не совсем многопоточность, но решает схожие задачи).

  2. multiprocessing — для CPU-bound задач (использует процессы, обходит GIL).

  3. queue — для безопасного обмена данными между потоками.

Для сложных сценариев можно использовать gevent или celery (распределённые задачи).

Ответ 18+ 🔞

Да ты посмотри, какая тут, блядь, кухня развернулась! Прямо как в столовой, когда на раздачу привезли котлеты — все лезут, сука, одновременно, а повариха с половником орёт. Так и с многопоточностью в Питоне, ёпта.

Ну, во-первых, есть у нас старый добрый threading. Это как взять одного работягу (интерпретатор) и сказать ему: «Вася, тащи пять мешков картошки!». Он вроде и пятью руками хватается, но по факту-то руки-то одни — GIL, блядь, этот проклятый! Так что для задач, где надо просто ждать (сеть, диск, база данных) — самое то. А вот если считать что-то тяжёлое — нихуя не выйдет, Вася с одним мешком упрётся, а остальные будут рядом пылиться.

import threading

def task():
    print("Thread running")

thread = threading.Thread(target=task)
thread.start()
thread.join()

А если тебе лень возиться с этими потоками вручную, как с тараканами по банкам раскладывать, есть concurrent.futures. Штука, блядь, удобная! Как пульт от телевизора. Хочешь пул потоков — ThreadPoolExecutor, хочешь процессов — ProcessPoolExecutor. Нажал кнопку — получил результат, не хуя себе!

from concurrent.futures import ThreadPoolExecutor

with ThreadPoolExecutor() as executor:
    executor.submit(lambda: print("Task executed"))

Дальше идёт asyncio. Это, сука, не совсем многопоточность, это такая хитрая жопа, где одна кухарка (поток) управляет двадцатью кастрюлями (корутинами). Пока одна кастрюля ждёт, пока закипит, она уже другую помешивает. Красота, да? Но мозги надо иметь, а то спагетти-код получишь — в рот меня чих-пых!

Ну а если задачи вообще монструозные, чисто вычислительные, то тут только multiprocessing. Это когда ты GIL'у говоришь: «Иди нахуй со своим замком!» — и запускаешь кучу отдельных питонов-процессов. У каждого свой GIL, своя память. Мощно, конечно, но и возни, блядь, овердохуища.

И конечно, куда ж без queue — чтобы эти потоки или процессы не подрались, как пацаны у ларька, из-за одной пачки сигарет. Кидай туда задания — пусть разбирают по очереди, цивилизованно.

А для совсем уже извращенцев, которым мало, есть gevent или celery. Последний — это вообще, блядь, распределённые задачи, можно на разных машинах гонять. Представляешь? Одна программа в Питере, другая в Хабаровске, а они друг другу сообщения шлют, как бабы на скамейке сплетничают.

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