Есть ли отличия в асинхронном и многопоточном коде в контексте Python?
========================================================================

 Подскажите, плз, в чем отличия выполнения кода в питона с его gil в асинхронном и многопоточном коде.  

Бывают ли кейсы когда на питоне лучше написать многопоточный код чем асинхронный ? 

 Если нужно конкурентно делать блокирующиеся вызовы, без потоков просто не обойтись. Асинхронность работает только тогда, когда вся цепочка вызовов от начала до конца асинхронная. 

 Поржал над комментариямя (без обид), хотя в принципе первый прав, в общем - как мы помним, у современных процессоров несколько ядер, плюс каждое ядро может выполнять несколько задач сразу и вот многопоточность - это когда несколько частей кода выполняются независимо, например два у вас работает программа, можно нажимать кнопки, она будет реагировать, но в отдельном потоке у неё будет идти цикл, который будет что-то считать.  

  

Асинхронность тоже позволяет выполнять два цикла, но суть её в том, что куски циклов выполняются по очереди, в одном потоке - первый цикл на половину, потом второй на половину, опять первый - с середины до конца, опять второй, тоже с середины до конца, и так по порядку.   

  

Но если использовать sleep() в Асинхронность, прервется выполнение всей программы, а в многопоточность прервется только тот поток где вызван sleep()  

  

В свое время минусом многопоточность является процесс гонки, это когда например мы запускаем 2 части кода в разных потоках, но части из 1 потока нужен результат из 2 потока, а тот в свою очередь ещё не получен, и появляется ошибка. Это надо уже решать по своему   

  

Вообще-то что использовать, зависит от задачи, но асинхронность все таки проще несмотря на некоторые минусы, и занимает меньше ресурсов компьютера, плюс некоторые известные библиотеки, например aiogram, используют именно асинхронность, так что стоит с ней разбираться (хотя и многопоточность тоже полезна) 

 На настоящей многопоточности можно полностью параллельно исполнять не-Python код, например, долго работающие вызовы математических библиотек. Или адапторы к базе данных часто не имеют асинхронной версии. С другой стороны, настоящие потоки довольно дорогие с точки зрения таких ресурсов, как стек и объекты ядра, что ограничивает их количество примерно 1000, но вообще лучше не более 50 без необходимости