2017-11-03 7 views
2

私はpy3.4のジェネレータベースのコルーチンを使用していましたが、いくつかのコルーチン呼び出しをreturn inner_coroutine()(以下の例のように)しています。しかし、私はpy3.5の本来のコルーチンを使用するように変換していますが、内部コルーチンが動かないので、もはや機能しないことがわかりました(下記の例を実行した結果を参照してください)。ネイティブの内部コルーチンを実行するには、元のreturn inner_coroutine()の代わりにreturn await inner_coroutine()を使用する必要があります。ネイティブのasyncioコルーチンを単に返すことでチェーン化することはできません

ネイティブコルーチンの連鎖が、ジェネレータベースのものと同じ方法で動作することを期待していました。私は何かを見逃しているのですか、これはネイティブコルーチンの実際の制限ですか?

import asyncio 

@asyncio.coroutine 
def coro(): 
    print("Inside coro") 

@asyncio.coroutine 
def outer_coro(): 
    print("Inside outer_coro") 
    return coro() 

async def native_coro(): 
    print("Inside native_coro") 

async def native_outer_coro(): 
    print("Inside native_outer_coro") 
    # return await native_coro() # this works! 
    return native_coro() 

loop = asyncio.get_event_loop() 
loop.run_until_complete(outer_coro()) 
loop.run_until_complete(native_outer_coro()) 

そして、その一例を実行しているから、出力:

Inside outer_coro 
Inside coro 
Inside native_outer_coro 
foo.py:26: RuntimeWarning: coroutine 'native_coro' was never awaited 
loop.run_until_complete(native_outer_coro()) 

答えて

1

は、これは別の答えと同じ内容ですが、私はへの応答として、理解しやすくなると思う方法で述べました質問。

Pythonは何かが発電機であるか、正常な機能は、それがyield文が含まれているかどうかであるか否かを判断する方法。 これにより、@asyncio.coroutineのあいまいさが発生します。あなたのコルーチンがすぐに実行されるかどうか、呼び出し側があなたのコードが実際にyield statementを含めることを起こるかどうかに依存したジェネレータオブジェクトにnextを呼び出すまで、それは待っているかどうか 。 ネイティブコルーチンは、たとえawaitステートメントを含まなくても、設計によってはっきりとはっきりしません。 これは予測可能な動作を提供しますが、使用しているチェーニングの形式を許可しません。あなたが指摘したように

return await inner_coroutine() 

がしかし構文を待つという点では注意しないイベントループに外側コルーチンを実行しながら あなたは、内側のコルーチンが呼び出されることができます。しかし、ジェネレータベースの手法では歩留まりがないため、実際にコルーチンをイベントループに投入しながら内部コルーチンが構築されます。 ほとんどの場合、この違いは関係ありません。

1

あなたの古いバージョンでは、間違ったロジックを持っていたし、不完全な発電機ベースの実装にのみ働きました。新しいシンタックスでこの機能を閉じ、asyncioをより一貫性のあるものにすることができました。コルーチンの

アイデアは、このように動作するようです:outer()を待っている...この例では

c = coro_func()  # create coroutine object 
coro_res = await c # await this object to get result 

...

@asyncio.coroutine 
def outer(): 
    return inner() 

inner()コルーチンオブジェクトではないこのオブジェクトの結果を返す必要があります 。しかし、実装が不完全であるため、inner()yield from inner()のように書かれています)が待っています。

新しい構文asyncioは、次のように正確に機能します。結果ではなく、coroutineオブジェクトを返します。そして、このコルーチンのオブジェクトは決して待たれていなかったので(通常は間違いを意味する)、この警告が表示されます。

あなたは明確にそれをすべて表示するには、このようにコードを変更することができます。

loop = asyncio.get_event_loop() 
print('old res:', loop.run_until_complete(outer_coro())) 
print('new res:', loop.run_until_complete(native_outer_coro())) 
関連する問題