2016-08-29 20 views
3

asyncioについては非常に特別なことが1つあります。これが非同期コールバックと同期コールバックの違いです。いくつかの例を紹介しましょう。asyncio:非同期と同期コールバックの理解

Asyncio TCP例:

class EchoServer(asyncio.Protocol): 

def connection_made(self, transport): 
    print('connection made') 

def data_received(self, data): 
    print('data received: ', data.decode()) 

def eof_received(self): 
    pass 

def connection_lost(self, exc): 
    print('connection lost:', exc) 

Aiohttp例:

async def simple(request): 
    return Response(text="Simple answer") 

async def init(loop): 
    app = Application(loop=loop) 
    app.router.add_get('/simple', simple) 
    return app 

loop = asyncio.get_event_loop() 
app = loop.run_until_complete(init(loop)) 
run_app(app, loop=loop) 

これらの2つの例は、機能的に非常に似ていますが、彼らは両方の異なった方法でそれをやっているように見えます。最初の例では、何らかのアクションで通知を受けたい場合は、同期関数(EchoServer.connection_made)を指定します。ただし、2番目の例では、何らかのアクションで通知を受けたい場合は、非同期コールバック関数(simple)を定義する必要があります。

この2つのタイプのコールバックの違いは何ですか。私は、通常の関数と非同期関数の違いを理解していますが、私はコールバックの違いについて私の頭を包むことはできません。たとえば、aiohttpのような非同期APIを作成したいと思ったら、何かをしてコールバックを呼び出す関数を用意していますが、引数として渡す非同期関数を要求する必要があるかどうかはどのように決定しますかまたは単に定期的な同期のもの? 、データベースへのアクセスだけ定期的に同期メソッドを呼び出す必要がありProtocol.data_received()でなど

をHTTPリクエストを行います。

答えて

1

aiohttpの例では、simpleウェブハンドラからの非同期呼び出しを行うことができます。

コールバックがデザインによって同期することになっている

Protocol UPD。 これらは、同期と非同期の間の非常に低レベルのブリッジです。 あなたは非同期コードを呼び出すことができますが、実際にはトリッキーなコーディングが必要です。ソケットなどのため ユーザレベルasyncio APIストリームである:https://docs.python.org/3/library/asyncio-stream.html

独自のコールバックシステムを導入する場合、コールバックは、非同期コードを呼び出したいことはありません、なぜあなたは100%確実でない限り、おそらくあなたは、非同期コールバックを必要とする必要があります。

通常の関数(def)とコルーチン(async def)のシグネチャは異なります。必要なシグネチャを変更するのは難しいです。特に、コードがライブラリとして公開されており、コールバックのすべてのユーザーを制御できない場合は特にそうです。

P.S.

パブリックAPIメソッドについても同様です。

ライブラリの開発中に私が学んだ最も難しい教訓は、最初は同期機能のみを呼び出すコルーチンでもあります。 socket.close()

しかし、後で、現在のアクティビティの終了などを待つ必要があり、正常なシャットダウンを追加することをお勧めします。ユーザーがobj.close()としてあなたのAPIを呼び出す持っていた場合

今、彼らはawait obj.close()を使用する必要がありますが、それは後方互換性のない変更です!

+0

しかし、私がイベントループへの参照を保持している場合でも、私は同期化された '' Protocol.data_received() ''でも非同期メソッドを呼び出すことができます。 –

+0

'Protocol.data_received()'で 'await'を使うことはできませんが、shoutdはタスクを作り、どこかのタスクの終了を待ちます。 –

+0

したがって、同期コールバックまたは非同期コールバックを必要とする関数を公開するかどうかは、APIの観点からは基本的に無関係です。あるいは、asyncioの開発者が厳密に '' Protocol''クラスで同期コールバックを必要とする特定の要因がありましたか? –

関連する問題