В чем причина этого ограничения?
Глядя на реализацию , причина, конечно, не техническая. Поскольку код уже вызывает ensure_future
(а не, скажем, create_task
), он будет автоматически работать и работать правильно на любом ожидаемом объекте.
Причину ограничения можно найти на трекере. Функция была добавлена в 2015 году в результате запроса pull . В обсуждении по теме bpo податель явно просит переименовать функцию в ensure_future_threadsafe
(параллельно ensure_future
) и принять любую приемлемую позицию, поддержанную Юрием Селивановым. Тем не менее, Гвидо был против идея:
Я против этой идеи. В любом случае я не вижу большого важного будущего для этого метода: это всего лишь немного клея между поточным миром и асинхронным миром, и люди узнают, как его использовать, найдя пример.
[...]
Но, честно говоря, я не хочу поощрять переключаться между потоками и циклами событий; Я вижу это как необходимое зло. Имя, которое у нас сейчас есть, отлично от POV того, кто кодирует в многопоточном мире и хочет передать что-то миру асинцио.
Зачем кому-то в многопоточном мире иметь asyncio.future, которого ему нужно ждать? Похоже, что они смешивают два мира - или они должны писать асинхронный код вместо многопоточного кода.
Есть другие комментарии в том же духе, но вышеприведенное в значительной степени суммирует аргумент.
Является ли функция wrapper
, определенная выше, наиболее обычным способом передачи ожидаемого в run_coroutine_threadsafe
и другие API, которые требуют асинхронного определения или определяемой генератором сопрограммы?
Если вам действительно нужен объект сопрограммы, то что-то вроде wrapper
, безусловно, является простым и правильным способом получить его.
Если единственная причина, по которой вы создаете оболочку, - это вызвать run_coroutine_threadsafe
, но вы на самом деле не интересуетесь результатом или concurrent.futures.Future
, возвращаемым run_coroutine_threadsafe
, вы можете избежать упаковки, вызвав call_soon_threadsafe
напрямую:
loop.call_soon_threadsafe(asyncio.ensure_future, awaitable)