Hey folks, I’m using motor for the first time, version 2.5.1. I have a twisted app that is using the asyncio reactor. My tests uses the pytest_twisted plugin with --reactor asyncio. I’m able to reproduce the error with the following code.
async def print_results():
client = AsyncIOMotorClient(test_db_uri)
db = client.get_default_database()
col = db.get_collection("user")
async for doc in col.find({}):
print(doc)
@defer.inlineCallbacks
def test_motor():
createSomeUsersWithMongoEngine()
yield defer.ensureDeferred(print_results())
The error I get is:
File "/usr/local/lib/python3.10/site-packages/twisted/internet/defer.py", line 1697, in _inlineCallbacks
result = context.run(gen.send, result)
File "test/test_reporting.py", line 318, in print_results
async for doc in col.find({}):
File "/usr/local/lib/python3.10/site-packages/motor/core.py", line 1158, in next
if self.alive and (self._buffer_size() or await self._get_more()):
RuntimeError: await wasn't used with future
It’s almost as if _get_more is not returning a future. Any ideas? This is using Python 3.10.11, twisted 22.10.0, and PyMongo 3.12.0.
Yes turns out you are right! Nothing to do with Motor at all. I have to turn the Motor future into a Deferred and then it works fine.
async def print_results():
client = AsyncIOMotorClient(test_db_uri)
db = client.get_default_database()
col = db.get_collection("user")
async for doc in col.find({}):
print(doc)
@defer.inlineCallbacks
def test_motor():
createSomeUsersWithMongoEngine()
yield Deferred.fromFuture(print_results())
Well, one thing I learned in this process is that Motor is actually not an asyncio driver for MongoDB. It’s actually just a wrapper on sync sockets (a wrapper of PyMongo actually) that simply runs the IO bound methods in a ThreadExecutorPool. Kind of disappointing. I was using txmongo that while old and dusty at least is a real async socket driver implementation for Mongo. I wonder if Mongo will ever have a modern trully async driver. I guess I can hope!