Документы asyncio проясняют, что код asyncio не должен вызывать код блокировки напрямую, а также указывает способ запуска кода блокировки с помощью asyn c code:
Blocking Код (связанный с ЦП) не должен вызываться напрямую. Например, если функция выполняет расчет с интенсивным использованием ЦП в течение 1 секунды, все параллельные задачи asyncio и операции ввода-вывода будут отложены на 1 секунду.
Исполнитель может использоваться для запуска задачи в другом потоке или даже в другом процессе, чтобы избежать блокировки потока ОС событием l oop.
Однако это описание не очень конкретно c относительно того, в какой момент следует использовать исполнителя. Понятно, что «вычисление интенсивного использования ЦП в течение 1 секунды» будет проблемой, но будет ли проблема 0,1 с? или 0,01 с?
В документации также приводится пример
def cpu_bound():
return sum(i * i for i in range(10 ** 7))
как что-то для запуска в экзекьюторе (который выполняется менее чем за секунду).
(Хотя они, вероятно, используют это как пример использования потоков и процессов, это все еще пример того, что я имею в виду - я бы запустил его в исполнителе, если бы это было range(10 ** 6)
, et c. )
В этом ответе указано, что
Большая часть стандартной библиотеки состоит из обычных, «блокирующих» функций и определений классов. Они выполняют свою работу быстро, поэтому, даже если они «блокируются», они возвращаются в разумные сроки.
...
Загрузка стандартных библиотечных функций и методов выполняется быстро, зачем вам это нужно? запустить str.splitlines()
или urllib.parse.quote()
в отдельном потоке, когда было бы намного быстрее просто выполнить код и покончить с ним?
Но что считается «разумным временем»? Когда я смогу «просто выполнить код и покончить с ним»?
Мои вопросы:
- Как вы определяете, что требуется исполнитель?
- Что на самом деле происходит, если ваш код слишком долго «блокируется»? Каковы признаки того, что это так?