【问题标题】:object MotorLatentCommandCursor can't be used in 'await' expression对象 MotorLatentCommandCursor 不能在“等待”表达式中使用
【发布时间】:2018-12-13 09:48:42
【问题描述】:

在 Tornado 中使用电机连接 mongodb

我创建了一个电机连接

import motor.motor_tornado
from tornado.web import RequestHandler
client = motor.motor_tornado.MotorClient('mongodb://xxx')

class BaseHandler(RequestHandler):
    @property
    def db(self):
        return client['realtime-test']

class Account(BaseHandler):
    async def get(self,*args,**kwargs):
        all_user = await self.db.account.aggregate([
            {'$match': {'status': 1}},
            {'$group': {'_id':''}}
        ])
        print(all_user)

当我开始时,我收到了这条消息: "对象 MotorLatentCommandCursor 不能用于 'await' 表达式"

我知道为什么〜这似乎没什么问题

【问题讨论】:

    标签: python mongodb tornado tornado-motor


    【解决方案1】:

    aggregate() 方法返回一个可以在循环中使用的游标。您不能在 await 语句中使用它,因为它不是等待对象。

    你会像这样使用它:

    async def get(self,*args,**kwargs):
        cursor = self.db.account.aggregate([
            {'$match': {'status': 1}},
            {'$group': {'_id':''}}
        ])
    
        all_user = []
    
        async for doc in cursor: 
            all_user.append(doc)
    
        print(all_user)
    

    【讨论】:

    • 对不起。但我也有一个问题。如果我需要一个结果列表,我可以只在 python 和 mongodb 中使用一个 I/O。所以当我将电机与 async for 一起使用时,我需要在每个 for 循环中获取每个 I/O,它需要大量 I/O蟒蛇和电机。我怎样才能让它变得更好
    • @Natee 你不必担心这个。因为 MongoDB 以大批量(默认为 101 个文档)返回查询结果。因此,async for 循环只会为 101 个文档执行一次 I/O,依此类推。来源:docs.mongodb.com/manual/tutorial/iterate-a-cursor/…
    【解决方案2】:

    在官方文档中说:一个可以在await表达式中使用的对象。可以是协程或带有 await() 方法的对象。 您可以从 PEP 492 获取更多信息:https://www.python.org/dev/peps/pep-0492/#asynchronous-iterators-and-async-for

    你也可以使用 asgiref 来包装你的函数:

    from asgiref.sync import sync_to_async
    import motor.motor_tornado
    from tornado.web import RequestHandler
    client = motor.motor_tornado.MotorClient('mongodb://xxx')
    
    class BaseHandler(RequestHandler):
        @property
        def db(self):
            return client['realtime-test']
    
    class Account(BaseHandler):
        async def get(self,*args,**kwargs):
            all_user = await sync_to_async(self.db.account.aggregate)([
                {'$match': {'status': 1}},
                {'$group': {'_id':''}}
            ])
            print(all_user)
    

    【讨论】:

      【解决方案3】:

      通过添加 to_list()。 这对我有用

      all_user = await self.db.account.aggregate([
                  {'$match': {'status': 1}},
                  {'$group': {'_id':''}}]).to_list(None)
      

      【讨论】:

        猜你喜欢
        • 2021-09-28
        • 2021-06-02
        • 2021-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-26
        相关资源
        最近更新 更多