2015-12-20 5 views
9

Ich wollte eine ThreadPoolExecutor von einem python coroutine verwenden, um einige blockierende Netzwerkaufrufe an einen separaten Thread zu delegieren. Allerdings läuft den folgenden Code:Zukunft erwarten von Executor: Future kann nicht in "erwarten" Ausdruck verwendet werden

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() 

Ursachen Fehler:

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

Sind nicht Future Objekte awaitable? Warum sagt es, dass sie es nicht sind? Wie kann ich await ein Future Objekt zurückgegeben von executor.submit?

Python 3.5.0

EDIT

executor.submit Verwendung ist nicht meine Entscheidung. Dies wird intern von mehreren Bibliotheken wie requests-futures verwendet. Ich suche nach einer Möglichkeit, mit diesen Modulen aus Coroutinen zu interagieren.

Antwort

17

Sie loop.run_in_executor verwenden sollten:

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 Objekt unterscheiden sich von asyncio.Future. Die asyncio.Future ist für die Verwendung mit Ereignisschleifen vorgesehen und ist zu erwarten, während ersteres nicht ist. loop.run_in_executor bietet die notwendige Interoperabilität zwischen den beiden.

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.

Obwohl nicht dokumentierte, können Sie asyncio.wrap_future(future, *, loop=None) verwenden, um eine concurrent.futures.Future zu einem asyncio.Future zu konvertieren.

+1

Ich weiß nicht, warum der Downvote. Das funktioniert sicher. Aber ich interessiere mich mehr für * warum * als für * wie *. Außerdem verwende ich die Futures-Requests-Bibliothek, die intern sendet. –

+0

Das einfache * warum * ist 'concurrent.futures.Future' ist nicht zu erwarten. Sie denken an 'asyncio.Future'. –

+0

Okay, also haben wir verschiedene Typen namens Future. Gibt es eine Konvertierung zwischen diesen Typen? –