Что такое синхронное программирование?
Что проверяют
Различаете ли вы «выполняется по очереди» и «блокирует поток», и знаете ли, чем это оборачивается в Python. Вопрос почти всегда ведёт к asyncio, потокам и GIL, поэтому ждут не определения из учебника, а понимания, что именно стоит в ожидании и чем это оплачено.
Как отвечать
Синхронный вызов не отдаёт управление, пока не получен результат: следующая строка ждёт. Асинхронный отдаёт сразу, результат забирают позже.
data = requests.get(url).text # поток стоит здесь
rows = parse(data)В Python синхронный стиль основной, и это не недостаток: под WSGI приложение обслуживает нагрузку несколькими процессами и потоками, каждый занят своим запросом. Проблема появляется, когда один процесс должен держать много одновременных ожиданий: тысяча открытых соединений это тысяча занятых потоков, а поток стоит памяти и переключений.
Здесь и появляется asyncio: await отдаёт управление циклу событий, и одна нить обслуживает сотни ожиданий. Оговорка обязательная: выигрыш только на вводе-выводе. Счётная нагрузка упирается в глобальную блокировку интерпретатора, её выносят в процессы через multiprocessing или ProcessPoolExecutor.
Сильный ответ заканчивается критерием выбора: немного одновременных соединений и простая логика это синхронный код, много ожиданий внутри одного процесса это asyncio, тяжёлые вычисления это процессы.
Где спотыкаются
Зовут синхронную библиотеку внутри async def. Один requests.get или time.sleep останавливает весь цикл событий вместе со всеми соединениями, и лечится это асинхронным клиентом либо выносом в asyncio.to_thread.
Считают асинхронность способом ускорить вычисления. Разбор большого файла в корутине быстрее не станет, зато соседние задачи перестанут выполняться до его конца.
Говорят, что синхронный код медленный сам по себе. Медленным его делает ожидание, а не последовательность: для короткой обработки синхронный обработчик и проще, и предсказуемее по задержке.