非同期Python 3.5およびMongodb


これは、 tornado使用されるmongodbの非同期ドライバーの主要な革新に関する記事のかなり無料の翻訳です。 この翻訳を書く主な動機は、 asyncioasyncawaitおよびPython 3.5サポートなど、このバージョンで登場した革新です。 この記事自体はイノベーションのリストではなく、 MongoDBでの非同期作業の簡潔な例です。


はじめに
非同期
集約する
Python 3.5
非同期および待機


はじめに


最近、 Mongodb Motor用のPythonドライバーの新しいBeta版が公開されました。 このバージョンには、最大のアップデートの1つが含まれています。 インストールには、次を使用できます。
python -m pip install --pre motor==0.5b0

Motor 0.5はまだPyMongo 2.8.0依存しています。 これはPyMongo古いバージョンですが、今回のリリースは非常に大きいため、3番目のバージョンに完全に切り替えるのに十分な時間はありませんでした。

非同期


Motorは、 Tornado代替としてasyncioと統合できるようにasyncioました。 Remy Jolin、Andrei Svetlov svetlov 、Nikolay Novikにasyncioでの作業のためのMotorの統合に多大な貢献をしてasyncioます。

Tornado asyncioasyncioは関連しています。 Tornado Motor例:
 # Tornado API from tornado import gen, ioloop from motor.motor_tornado import MotorClient @gen.coroutine def f(): result = yield client.db.collection.insert({'_id': 1}) print(result) client = MotorClient() ioloop.IOLoop.current().run_sync(f) 

そして、これがasyncioの例​​です:
 import asyncio from motor.motor_asyncio import AsyncIOMotorClient @asyncio.coroutine def f(): result = yield from client.db.collection.insert({'_id': 1}) print(result) client = AsyncIOMotorClient() asyncio.get_event_loop().run_until_complete(f()) 

Tornadoとは異なり、 asynciohttp実装が含まれておらず、さらにフレームワークではありません。 これを行うには、Andrei Svetlovのaiohttpライブラリを使用します。 Motorがaiohttpで動作する小さな

集約する


MotorCollection.aggregateはデフォルトでカーソルを返し、カーソルはyieldなしで直接戻ります。 古い構文はサポートされなくなりました:
 # Motor 0.4 and older, no longer supported. cursor = yield collection.aggregate(pipeline, cursor={}) while (yield cursor.fetch_next): doc = cursor.next_object() print(doc) 

Motor 0.5ようにします。
 # Motor 0.5: no "cursor={}", no "yield". cursor = collection.aggregate(pipeline) while (yield cursor.fetch_next): doc = cursor.next_object() print(doc) 

asyncioはこれにyield fromを使用します。
 # Motor 0.5 with asyncio. cursor = collection.aggregate(pipeline) while (yield from cursor.fetch_next): doc = cursor.next_object() print(doc) 

Python 3.5


Motorは現在、 Python 3.5と互換性があり、多少の労力が必要です。 Motorはコルーチンで動作するだけでなく、 MotorClient.openMotorGridFS.putなどの機能の一部を内部的に使用してコルーチンを使用するため、これは困難でした
Python 2.6Python 3.4で動作するコルーチンを記述する方法がありましたが、 Python 3.5では最終的に壊れました。 Python 3.5ネイティブコルーチンまたはPython 2コルーチンベースのジェネレーターに値を返す単一の方法はないため、値を返すすべての内部motorコルーチンはコールバックを使用して書き換えられています。

非同期および待機


Python 3.5との統合に費やされた努力に対する報酬は、 asyncおよびawait構文で記述されたネイティブコルーチンでmotor動作するようになったことです。
 async def f(): await collection.insert({'_id': 1}) 

MotorCollection.findMotorCollection.aggregate 、またはMotorGridFS.findのカーソルは、 次の async forしてネイティブコルーチンに美しく、非常に効率的に統合できます。
 async def f(): async for doc in collection.find(): print(doc) 

どのくらい効果的ですか? 10,000ドキュメントのコレクションの場合、このコード例は0.14秒で実行されました。
 # Motor 0.5 with Tornado. @gen.coroutine def f(): cursor = collection.find() while (yield cursor.fetch_next): doc = cursor.next_object() print(doc) 


gen.coroutineyieldasyncawaitに単純にgen.coroutine次のコードは、同様のことを行います。
 # Motor 0.5 with Tornado, using async and await. async def f(): cursor = collection.find() while (await cursor.fetch_next): doc = cursor.next_object() print(doc) 

ただし、 async forでは0.04秒かかり、3倍高速です。
 # Motor 0.5 with Tornado, using async for. async def f(): cursor = collection.find() async for doc in cursor: print(doc) 

ただし、to_listのMotorCursorは依然として大きな役割を果たします。
 # Motor 0.5 with Tornado, using to_list. async def f(): cursor = collection.find() docs = await cursor.to_list(length=100) while docs: for doc in docs: print(doc) docs = await cursor.to_list(length=100) 

to_listた関数は非同期の2倍の速度ですが、見た目はそれほど美しくなく、チャンクのサイズを指定する必要があります。 async forは非常にスタイリッシュasync for見え、ほとんどの場合に使用できるほど高速に動作すると思います。

motorリリースのベータ版は常に公開されていませんでしたが、今回は別の方法で公開されました。 motorへのasyncioの統合は、まったく新しいものです。 また、 motorコアの広範なリファクタリングと既存のtornado統合の書き直しが必要だったため、すべての欠落を修正するためにベータ版がリリースされました。

PS PMに書き込むための文法エラーと翻訳エラーのリクエスト。

Source: https://habr.com/ru/post/J270709/


All Articles