Мой вопрос: могу ли я перевести concurrent.future.Future
на asyncio.Future
(или наоборот)?
Если под «переносом» вы подразумеваете «преобразование одного в другое», то да, это возможно, хотя для устранения несоответствия импеданса между подходами может потребоваться определенная работа.
Чтобы преобразовать concurrent.futures.Future
в asyncio.Future
, вы можете позвонить asyncio.wrap_future
. Возвращенное будущее asyncio ожидаемо в цикле событий asyncio и завершится, когда завершится базовое будущее потоков. Это эффективный способ реализации run_in_executor
.
Нет общедоступной функциональности для непосредственного преобразования будущего asyncio в будущее concurrent.futures
, но есть функция asyncio.run_coroutine_threadsafe
, которая принимает сопрограмму , передает ее в цикл обработки событий и возвращает параллельное будущее, которое завершается, когда будущее асинцио. Это может быть использовано для эффективного преобразования любого асинхронного будущего в параллельное будущее, например:
def to_concurrent(fut, loop):
async def wait():
await fut
return asyncio.run_coroutine_threadsafe(wait(), loop)
Возвращенное будущее будет вести себя так, как вы ожидаете от параллельного будущего, например его метод result()
будет блокировать и т. д. Одна вещь, о которой вы могли бы позаботиться, это то, что обратные вызовы выполняются с add_done_callback
(как всегда), запущенным в потоке, который завершает будущее, которое в этом случае является потоком цикла обработки событий. Это означает, что если вы добавляете готовые обратные вызовы, вы должны быть осторожны, чтобы не вызывать блокирующие вызовы в их реализации, чтобы не блокировать цикл обработки событий.