1

私は自分のコードの次の簡略化されたバージョンを書きました:

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()

実行すると、次の 2 つのエラーのいずれかまたはまったく発生しません。

Exception ignored in: <bound method MotorCursor.__del__ of MotorCursor(<pymongo.cursor.Cursor object at 0x7fd3a31e5400>)>
Traceback (most recent call last):
  File "./env/lib/python3.4/site-packages/motor/__init__.py", line 1798, in __del__
TypeError: 'NoneType' object is not callable
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

Python 3.4.3、Tornado 4.1、Pymongo 2.8、Motor 0.4.1、および MongoDB 2.6.3 を使用しています。

この問題は、tailableおよびawait_dataオプションがTrueカーソルの作成時にのみ発生します。

カーソルを閉じないと、Pymongo のエラーも発生します。しかし、テーラブルカーソルなので、明示的に閉じる必要があると思います。

私はそれをグーグルで検索しましたが、運がありませんでした。助言がありますか?

4

1 に答える 1

1

This was an unknown bug in Motor, I've tracked and fixed it at MOTOR-67. You observed a couple problems.

First, the Motor cursor's destructor had a bug where it would try to send a "killcursors" message to the MongoDB server, even after you'd called close. You closed the cursor, disconnected the client, and exited the Python interpreter. During interpreter shutdown, the cursor is destroyed and tries to send "killcursors" to the server, but the client is disconnected so the operation fails and logs a warning. This is the bug I've fixed and will release in Motor 0.6.

You call exit() from within a function that has a reference to a cursor, so the cursor's destructor runs during interpreter shutdown. The shutdown sequence is complex and unpredictable; often, the destructor runs after the greenlet module is destroyed. When the cursor destructor calls greenlet.getcurrent() at line 1798, the getcurrent function has already been set to None, hence "TypeError: 'NoneType' object is not callable".

I recommend not calling "exit()" from within a function. Your call to IOLoop.current().stop() allows the start function to return, and the interpreter to exit gracefully.

于 2016-03-05T15:37:47.333 に答える