为什么在使用可裁剪的MotorCursor并关闭Motor客户机连接时会出现被忽略的异常?

2024-05-13 21:36:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我编写了以下代码的简化版本:

from sys import exit
from tornado.ioloop import IOLoop
from tornado.gen import coroutine
from pymongo.errors import CollectionInvalid
from motor import MotorClient


client = MotorClient()
db = client.db_test
coll_name = 'coll_test'
coll = db[coll_name]
cursor = None


@coroutine
def stop():
    yield cursor.close()
    client.disconnect()
    IOLoop.current().stop()
    exit()


@coroutine
def create_cursor():
    global cursor

    try:
        yield db.create_collection(coll_name, capped=True, size=1000000)

    except CollectionInvalid:
        print('Database alredy exists!')

    yield coll.save({})
    yield coll.save({})
    cursor = coll.find(tailable=True, await_data=True)
    yield cursor.fetch_next
    cursor.next_object()

if __name__ == "__main__":
    IOLoop.current().spawn_callback(create_cursor)
    IOLoop.current().call_later(10, stop)
    IOLoop.current().start()

当我运行它时,我随机得到以下两个错误中的一个或一个:

^{pr2}$
Exception ignored in: <bound method MotorCursor.__del__ of MotorCursor(<pymongo.cursor.Cursor object at 0x7f4bea529c50>)>
Traceback (most recent call last):
  File "./env/lib/python3.4/site-packages/motor/__init__.py", line 1803, in __del__
  File "./env/lib/python3.4/site-packages/motor/__init__.py", line 631, in wrapper
  File "./env/lib/python3.4/site-packages/tornado/gen.py", line 204, in wrapper
TypeError: isinstance() arg 2 must be a type or tuple of types

我使用的是python3.4.3、Tornado 4.1、Pymongo 2.8、motor0.4.1和MongoDB 2.6.3。在

只有在创建游标时tailableawait_data选项为True时才会出现此问题。在

当我不关闭光标时,我也会得到Pymongo的错误。但我认为我应该显式地关闭它,因为它是一个可裁剪的光标。在

我在谷歌上查过了,但我没有运气。有什么建议吗?在


Tags: nameinfromimportclienttruedbcurrent
1条回答
网友
1楼 · 发布于 2024-05-13 21:36:52

这是马达中的一个未知错误,我已经在MOTOR-67上跟踪并修复了它。你发现了一些问题。在

首先,Motor cursor的析构函数有一个bug,它会试图向MongoDB服务器发送一条“killcursors”消息,甚至在您调用close之后。您关闭了光标,断开了客户机的连接,并退出了Python解释器。在解释器关闭期间,光标被破坏并试图向服务器发送“killcursors”,但客户端断开连接,因此操作失败并记录警告。这是我已经修复的bug,将在motor0.6中发布。在

在引用了游标的函数中调用exit(),因此在解释器关闭期间,游标的析构函数将运行。关闭序列非常复杂且不可预测;通常,析构函数在greenlet模块被破坏后运行。当游标析构函数在line 1798调用greenlet.getcurrent()时,getcurrent函数已设置为None,因此“TypeError:'NoneType”对象不可调用。在

我建议不要在函数中调用“exit()”。对IOLoop.current().stop()的调用允许start函数返回,并允许解释器优雅地退出。在

相关问题 更多 >