Почему я получаю игнорируемые исключения при использовании настраиваемого MotorCursor и закрытии клиентского соединения Motor?
Я написал следующую упрощенную версию моего кода:
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()
Когда я запускаю его, я случайно не получаю ни одной, ни одной из следующих двух ошибок:
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. Но я думаю, что я должен явно закрыть его, потому что это настраиваемый курсор.
Я гуглил это, но мне не повезло. Какие-либо предложения?
1 ответ
Это была неизвестная ошибка в Motor, я отследил и исправил ее на MOTOR-67. Вы наблюдали пару проблем.
Во-первых, у деструктора движка Motor была ошибка, из-за которой он пытался отправить сообщение "killcursors" на сервер MongoDB, даже после того, как вы вызвали close. Вы закрыли курсор, отключили клиент и вышли из интерпретатора Python. Во время выключения интерпретатора курсор уничтожается и пытается отправить "killcursors" на сервер, но клиент отключается, поэтому операция завершается неудачно и регистрирует предупреждение. Это ошибка, которую я исправил и выпустит в Мотор 0.6.
Вы вызываете exit() из функции, которая имеет ссылку на курсор, поэтому деструктор курсора запускается во время выключения интерпретатора. Последовательность выключения является сложной и непредсказуемой; часто деструктор бежит за greenlet
Модуль уничтожен. Когда деструктор курсора вызывает greenlet.getcurrent()
на линии 1798 г. getcurrent
функция уже была установлена на None
следовательно, "TypeError: объект NoneType не может быть вызван".
Я рекомендую не вызывать "exit()" из функции. Ваш звонок в IOLoop.current().stop()
позволяет start
функция, чтобы вернуться, и интерпретатор, чтобы выйти изящно.