2017-01-17 4 views
1

を失敗し収量は動作しますが、非同期DEFからの収量は、次のコードは正常に動作します

import asyncio 
loop = asyncio.get_event_loop() 
async def a(): 
    print('hello') 
def b(): 
    yield from a() # <=========== only 1 tiny change 
loop.run_until_complete(b()) 
loop.close() 
print('done') 

@asyncio.coroutinebはそれが仕事になり飾ります。

デコレータ@asyncio.coroutineがないと、コードの最初の部分が正常に動作するのはなぜですか?ドキュメントは明らかにasyncio.sleepがコルーチンであると言うので、aなので、なぜコードは1つのケースで失敗し、もう1つのケースで正常に動作しますか?

答えて

3

あなたのコードは、次のエラーを生成します。

... 
     yield from a() # <=========== only 1 tiny change 
TypeError: cannot 'yield from' a coroutine object in a non-coroutine generator 

は明らかなようにasyncioを使用しているとき、あなたはコルーチンをマークする@coroutineまたはasync defを使用する必要がありますいずれか、エラーメッセージに記載されています。

import asyncio 


async def a(): 
    print('hello') 


async def b(): 
    await a() 


loop = asyncio.get_event_loop() 
loop.run_until_complete(b()) 
loop.close() 
print('done') 

または、Pythonの3.4のために:async def秒で、awaitではなくyield fromの使用すべきである

import asyncio 

@asyncio.coroutine 
def a(): 
    print('hello') 


@asyncio.coroutine 
def b(): 
    yield from a() 


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

print('done') 

あなたの最初の例は、 "バグだらけ" と考えられているが、run_until_completeので、それは "適切に" 実行されていますiscoroutineは、現在、発電機(defyield/yield fromとなります)に対してTrueを返しますが、これは将来のバージョンのPythonで変更される可能性のある実装の詳細です。 (async def a()の代わりに)def a()@couroutineを使用するか、またはdef a()yield from asyncio.sleep(1)を追加するだけで、2番目の例も実行されます。 asyncioでコルーチンとしてマークされていないジェネレータを使用しているときは、現在Pythonは "慈悲深い"かもしれませんが、async defsを使用しているときはそうではありません。

+0

ありがとうございます@udiここに興味のある別のパズルがあります:http://stackoverflow.com/questions/41708609/unfair-scheduling-bad-lock-optimization-in-asyncio-event-loop – user2297550

関連する問題