2015-12-20 12 views
9

Volevo utilizzare uno ThreadPoolExecutor da un python coroutine per delegare alcune chiamate di rete di blocco a un thread separato. Tuttavia, l'esecuzione il codice seguente:Attesa futuro dall'esecutore: Futuro non può essere utilizzato nell'espressione 'attendi'

from concurrent.futures import ThreadPoolExecutor 
import asyncio 

def work(): 
    # do some blocking io 
    pass 

async def main(): 
    executor = ThreadPoolExecutor() 
    await executor.submit(work) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(main()) 
loop.close() 

cause di errore:

TypeError: object Future can't be used in 'await' expression 

non sono Future oggetti awaitable? Perché dice che non lo sono?

Come posso await un oggetto Future restituito da executor.submit?

Python 3.5.0

EDIT

Utilizzando executor.submit non è la mia decisione. Questo è usato internamente da diverse librerie, come requests-futures. Sto cercando un modo per interoperare con questi moduli con le coroutine.

risposta

17

Si dovrebbe usare loop.run_in_executor:

from concurrent.futures import ThreadPoolExecutor 
import asyncio 

def work(): 
    # do some blocking io 
    pass 

async def main(loop): 
    executor = ThreadPoolExecutor() 
    await loop.run_in_executor(executor, work) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(main(loop)) 
loop.close() 

EDIT

concurrent.futures.Future oggetto sono diversi da asyncio.Future. Lo asyncio.Future deve essere utilizzato con i loop di eventi ed è attendibile, mentre il primo non lo è. loop.run_in_executor fornisce l'interoperabilità necessaria tra i due.

EDIT # 2

Using executor.submit is not my decision. This is used internally by several libraries, like requests-futures. I am searching for a way to interop with those modules from coroutines.

Anche se privi di documenti, è possibile utilizzare per convertire un asyncio.wrap_future(future, *, loop=None)concurrent.futures.Future ad un asyncio.Future.

+1

Non so perché il downvote. Questo certamente funziona. Comunque sono più interessato a * perché * piuttosto che a * come *. Inoltre, io uso la libreria delle richieste future, che usa invia internamente. –

+0

Il semplice * perché * è 'concurrent.futures.Future' non è attendibile. Stai pensando a 'asyncio.Future'. –

+0

Ok, quindi abbiamo diversi tipi chiamati Future. C'è una conversione tra questi tipi? –