SQLAlchemy и pg8000 KeyError / Broken Pipe в Google App Engine с Postgresql - PullRequest
1 голос
/ 07 февраля 2020

Моя цель - успешно выполнить операторы Select на моем Postgresql dv (на облаке SQL), используя ORM SQLAlchemy в моем приложении Flask в Google App Engine.

Я могу успешно развернуть приложение, и оно успешно подключается к базе данных и выдает операторы select. Однако примерно через 1 час работы приложения я начинаю получать следующие ошибки из запросов. Обратите внимание, что эти запросы успешно выполнялись до 1 часа, и я могу успешно выполнить запросы к базе данных из pgAdmin или локального python кода.

Есть две ошибки, первая - это ошибка KeyError в строке 1778 в pg8000 / core.py. На git эта строка имеет вид https://github.com/tlocke/pg8000/blob/master/pg8000/core.py#L1783

Это ошибка, которая обрабатывается с помощью блока исключения, но внутри этого блока, кроме блока, возникает ошибка Broken Pip.

File "/env/lib/python3.7/site-packages/pg8000/core.py", line 1778, in execute ps = cache['ps'][key] KeyError: ('SELECT voice_comments.id AS voice_comments_id, voice_comments.store_id AS voice_comments_store_id, voice_comments.comment_date AS voice_comments_comment_date, voice_comments.survey_item AS voice_comments_survey_item, voice_comments.comment_text AS voice_comments_comment_text, voice_comments.overall_satisfaction AS voice_comments_overall_satisfaction, voice_comments.visit_date AS voice_comments_visit_date \nFROM voice_comments \nWHERE voice_comments.store_id = %s AND voice_comments.comment_date >= %s AND voice_comments.comment_date <= %s AND voice_comments.overall_satisfaction = %s AND voice_comments.id NOT IN (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)', ((705, 0, <function Connection.__init__.<locals>.text_out at 0x3eb1a3fb7c20>), (1114, 1, <function timestamp_send_integer at 0x3eb1a4a6d320>), (1114, 1, <function timestamp_send_integer at 0x3eb1a4a6d320>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>), (21, 1, <built-in method pack of Struct object at 0x3eb1a4a41030>)))

В блоке исключений, который обрабатывает вышеуказанное KeyError, возникает BrokenPipeError, а именно:

Traceback (most recent call last): File "/env/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app response = self.full_dispatch_request() File "/env/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request rv = self.handle_user_exception(e) File "/env/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception reraise(exc_type, exc_value, tb) File "/env/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise raise value File "/env/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request rv = self.dispatch_request() File "/env/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "/srv/routes/voice.py", line 26, in voice_comments result = get_voice_comments(store_id, start_date, end_date, ids_to_filter_out=used_comment_ids) File "/srv/routes/pgsql_api.py", line 18, in get_voice_comments voice_comments.id.notin_(ids_to_filter_out)).all() File "/env/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3233, in all return list(self) File "/env/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3389, in __iter__ return self._execute_and_instances(context) File "/env/lib/python3.7/site-packages/sqlalchemy/orm/query.py", line 3414, in _execute_and_instances result = conn.execute(querycontext.statement, self._params) File "/env/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 982, in execute return meth(self, multiparams, params) File "/env/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 293, in _execute_on_connection return connection._execute_clauseelement(self, multiparams, params) File "/env/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1101, in _execute_clauseelement distilled_params, File "/env/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1250, in _execute_context e, statement, parameters, cursor, context File "/env/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1478, in _handle_dbapi_exception util.reraise(*exc_info) File "/env/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 153, in reraise raise value File "/env/lib/python3.7/site-packages/sqlalchemy/engine/base.py", line 1246, in _execute_context cursor, statement, parameters, context File "/env/lib/python3.7/site-packages/sqlalchemy/engine/default.py", line 588, in do_execute cursor.execute(statement, parameters) File "/env/lib/python3.7/site-packages/pg8000/core.py", line 861, in execute self._c.execute(self, operation, args) File "/env/lib/python3.7/site-packages/pg8000/core.py", line 1830, in execute self._flush() File "/opt/python3.7/lib/python3.7/socket.py", line 607, in write return self._sock.send(b) BrokenPipeError: [Errno 32] Broken pipe

Я думаю об этом в 3 частях:

1. Я недавно переключился с MySQL на PostgresSQL. С MySQL я не испытывал ошибок Broken Pipe ... или, по крайней мере, они были обработаны изящно за кулисами без моего ведома. Я беспокоюсь, что я делаю что-то глупое на высоком уровне .. т.е. я должен установить другие значения pool_recycle или connect_timeout при создании движка с SQLAlchemy. Я использую значения по умолчанию для всех аргументов, за исключением pool_timeout = 30, pool_recycle = 1800

Поскольку это происходит примерно через час после запуска приложения, мне интересно, отключается ли соединение (с помощью pg db), но SQLAlchemy все еще пытается их использовать?

2. Должен ли я беспокоиться о KeyError вообще? Или это ожидаемый путь в коде. Я склоняюсь к тому, чтобы быть ожидаемым, так как он пойман блоком исключений et c ...

3. Является ли BrokenPipeError чем-то, что я должен обработать на уровне запроса? то есть что-то вроде:

retry = 0
while retry<3:
try:
    session.query(....
    break
except BrokenPipeError:
    retry += 1
    continue

Ответы [ 2 ]

0 голосов
/ 01 марта 2020

Я неправильно определял область сеанса sqlalchemy, как описано здесь:

https://flask.palletsprojects.com/en/1.1.x/patterns/sqlalchemy/

В частности, я использовал scoped_session, но я не удалял сеанс с декоратором @ app.teardown_context.

Я делал это с mysql db, но просто забыл это сделать, когда переключился на pg sql.

Исправления это исправило проблему.

0 голосов
/ 10 февраля 2020

Возможно, вы закрываете канал при выполнении запроса. Согласно этому другому потоку stackoverflow о Как предотвратить BrokenPipeError это распространенная проблема. Здесь у вас есть краткое резюме:

BrokenPipeError нормально, как сказал фантом, потому что процесс чтения (голова) завершается и закрывает свой конец канала, в то время как процесс записи (python) все еще пытается написать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...