Почему я получаю игнорируемые исключения при использовании настраиваемого 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 функция, чтобы вернуться, и интерпретатор, чтобы выйти изящно.

Другие вопросы по тегам