これは、
tornado
使用される
mongodb
の非同期ドライバーの主要な革新に関する記事のかなり無料の翻訳です。 この翻訳を書く主な動機は、
asyncio
、
async
、
await
および
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
asyncio
と
asyncio
は関連しています。
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
とは異なり、
asyncio
は
http
実装が含まれておらず、さらにフレームワークではありません。 これを行うには、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.openやMotorGridFS.putなどの機能の一部を内部的に使用してコルーチンを使用するため、これは困難でした 。
Python 2.6
と
Python 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.find 、 MotorCollection.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.coroutine
と
yield
を
async
と
await
に単純に
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に書き込むための文法エラーと翻訳エラーのリクエスト。