2016-07-24 25 views
7

Rozważmy współprogram który wzywa do innego współprogram:W jaki sposób wywołujemy normalną funkcję, gdy spodziewany jest coroutine?

async def foo(bar): 
    result = await bar() 
    return result 

Działa to dobrze jeśli bar jest współprogram. Co muszę zrobić (tj. Co jest potrzebne, aby zawinąć połączenie pod numer bar), aby ten kod działał prawidłowo, jeśli bar jest normalną funkcją?

Jest całkowicie możliwe zdefiniowanie coroutine z async def, nawet jeśli nigdy nie robi nic asynchronicznego (tj. Nigdy nie używa await). Jednak pytanie dotyczy sposobu zawijania/modyfikowania/wywoływania zwykłej funkcji bar wewnątrz kodu dla foo, tak aby można było oczekiwać bar.

Odpowiedz

6

Wystarczy owinąć synchroniczne funkcji z asyncio.coroutine razie potrzeby:

if not asyncio.iscoroutinefunction(bar): 
    bar = asyncio.coroutine(bar) 

Ponieważ jest to bezpieczne, aby ponownie zawinąć współprogram test funkcja współprogram jest rzeczywiście nie jest wymagane:

async_bar = asyncio.coroutine(sync_or_async_bar) 

Dlatego Twój kod może zostać ponownie napisany w następujący sposób:

async def foo(bar): 
    return await asyncio.coroutine(bar)() 
+0

Wygląda na to, że działa. Zauważ, co ciekawe, że 'asyncio.coroutine (normal_function)()' jest generatorem, podczas gdy 'a_coroutine_function()' jest coroutine. – DanielSank

+0

Czy istnieje sposób traktowania obiektu generatora, który zwraca jak obiekt zadania, wywoływania 'Task.done()' i sprawdzania, czy nadal działa? – Dagrooms

Powiązane problemy