У меня есть приложение flask, которое запрашивает базу данных и возвращает около 250 тыс. Строк, преобразует их в формат JSON и передает результат клиенту. Я использую python генераторы для достижения потоковой передачи. Это выглядит примерно следующим образом:
@contextlib.contextmanager
def getKeyConnection():
with keypoolsem:
cnx = keycnxpool.get_connection()
try:
yield cnx
finally:
cnx.close()
@contextlib.contextmanager
def getKeyConnectionCursor():
with getKeyConnection() as db:
cursor = db.cursor(dictionary=True)
try:
yield cursor
finally:
cursor.close()
def segmentsInComputationGenerator(computation):
with getKeyConnectionCursor() as cursor:
cursor.execute(/*params*/)
results = cursor.fetchmany(fetchWidth)
yield '['
while results:
output = ""
//transform data to json
results = cursor.fetchmany(fetchWidth)
yield output
yield ']'
Проблема возникает, когда клиент завершает соединение с конечной точкой до того, как ВСЕ результаты будут доставлены. В этом случае менеджер контекста для курсора должен закрыть курсор, что, как я понимаю в документации (https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-close.html), означает, что непрочитанные результаты сбрасываются. Тем не менее, этого не происходит, кажется, что на курсор выдается ошибка.close ():
OperationalError(-1, 'MySQL Connection not available.', None)
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/wsgi.py", line 147, in respond
self.write(chunk)
File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/wsgi.py", line 228, in write
self.req.write(chunk)
File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/server.py", line 1112, in write
self.conn.wfile.write(chunk)
File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/makefile.py", line 36, in write
self._flush_unlocked()
File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/makefile.py", line 45, in _flush_unlocked
n = self.raw.write(bytes(self._write_buf))
File "/usr/lib/python3.6/socket.py", line 604, in write
return self._sock.send(b)
BrokenPipeError: [Errno 32] Broken pipe
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "api.py", line 81, in getKeyConnectionCursor
yield cursor
File "api.py", line 699, in segmentsInComputationGenerator
yield output
GeneratorExit
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "api.py", line 72, in getKeyConnection
yield cnx
File "api.py", line 83, in getKeyConnectionCursor
cursor.close()
File "/home/ubuntu/.local/lib/python3.6/site-packages/mysql/connector/cursor.py", line 388, in close
self._connection.handle_unread_result()
File "/home/ubuntu/.local/lib/python3.6/site-packages/mysql/connector/connection.py", line 1063, in handle_unread_result
raise errors.InternalError("Unread result found")
mysql.connector.errors.InternalError: Unread result found
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/server.py", line 1252, in communicate
req.respond()
File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/server.py", line 1056, in respond
self.server.gateway(self).respond()
File "/home/ubuntu/.local/lib/python3.6/site-packages/cheroot/wsgi.py", line 152, in respond
response.close()
File "/home/ubuntu/.local/lib/python3.6/site-packages/werkzeug/wsgi.py", line 874, in close
callback()
File "/home/ubuntu/.local/lib/python3.6/site-packages/werkzeug/wrappers.py", line 1164, in close
self.response.close()
File "api.py", line 700, in segmentsInComputationGenerator
yield ']'
File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
self.gen.throw(type, value, traceback)
File "api.py", line 83, in getKeyConnectionCursor
cursor.close()
File "/usr/lib/python3.6/contextlib.py", line 99, in __exit__
self.gen.throw(type, value, traceback)
File "api.py", line 74, in getKeyConnection
cnx.close()
File "/home/ubuntu/.local/lib/python3.6/site-packages/mysql/connector/pooling.py", line 118, in close
cnx.reset_session()
File "/home/ubuntu/.local/lib/python3.6/site-packages/mysql/connector/connection.py", line 713, in reset_session
raise errors.OperationalError("MySQL Connection not available.")
mysql.connector.errors.OperationalError: MySQL Connection not available.
Кажется, что курсор ожидает, что не будет непрочитанных результатов, когда cursor.close () вызываемый, что противоречит интерпретации документации , Как правильно удалить непрочитанные результаты из курсора в менеджере контекста?