我有一个每分钟运行 2 个任务的应用程序。除了它们所通信的 API 端点(见下文)之外,它们都具有几乎相同的代码。运行任务时,我会收到以下错误仅在调用之前
Base.metadata.create_all(engine)
:
[2022-05-06 16:45:00,110: WARNING/ForkPoolWorker-2] Traceback (most recent call last):
[2022-05-06 16:45:00,110: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1799, in _execute_context
self.dialect.do_execute(
[2022-05-06 16:45:00,110: WARNING/ForkPoolWorker-1] Traceback (most recent call last):
[2022-05-06 16:45:00,110: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 717, in do_execute
cursor.execute(statement, parameters)
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-1] File "tasks.py", line 25, in run_logger_task
accounts = db.get_accounts()
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-2] **psycopg2.DatabaseError: error with status PGRES_TUPLES_OK and no message from the libpq**
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-1] File "db_manager/crud.py", line 59, in get_accounts
**return self.session.query(Account).all()**
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-2] The above exception was the direct cause of the following exception:
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2711, in all
return self._iter().all()
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-2] Traceback (most recent call last):
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2846, in _iter
result = self.session.execute(
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-2] File "tasks.py", line 25, in run_logger_task
accounts = db.get_accounts() # TODO: encapsulate and move to crud?
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-2] File "db_manager/crud.py", line 59, in get_accounts
return self.session.query(Account).all()
[2022-05-06 16:45:00,111: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 1692, in execute
result = compile_state_cls.orm_setup_cursor_result(
[2022-05-06 16:45:00,112: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2711, in all
return self._iter().all()
[2022-05-06 16:45:00,113: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/context.py", line 333, in orm_setup_cursor_result
return loading.instances(result, querycontext)
[2022-05-06 16:45:00,113: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/query.py", line 2846, in _iter
result = self.session.execute(
[2022-05-06 16:45:00,114: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/loading.py", line 89, in instances
cursor.close()
[2022-05-06 16:45:00,120: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 1689, in execute
result = conn._execute_20(statement, params or {}, execution_options)
[2022-05-06 16:45:00,120: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 70, in __exit__
compat.raise_(
[2022-05-06 16:45:00,120: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
[2022-05-06 16:45:00,120: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1611, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
[2022-05-06 16:45:00,120: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/loading.py", line 69, in instances
*[
[2022-05-06 16:45:00,121: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
return connection._execute_clauseelement(
[2022-05-06 16:45:00,121: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/loading.py", line 70, in <listcomp>
query_entity.row_processor(context, cursor)
[2022-05-06 16:45:00,121: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1478, in _execute_clauseelement
ret = self._execute_context(
[2022-05-06 16:45:00,121: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/context.py", line 2484, in row_processor
_instance = loading._instance_processor(
[2022-05-06 16:45:00,122: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1842, in _execute_context
self._handle_dbapi_exception(
[2022-05-06 16:45:00,122: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/orm/loading.py", line 709, in _instance_processor
primary_key_getter = result._tuple_getter(pk_cols)
[2022-05-06 16:45:00,122: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 2023, in _handle_dbapi_exception
util.raise_(
[2022-05-06 16:45:00,122: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 901, in _tuple_getter
return self._metadata._row_as_tuple_getter(keys)
[2022-05-06 16:45:00,122: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 207, in raise_
raise exception
[2022-05-06 16:45:00,122: WARNING/ForkPoolWorker-1] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/result.py", line 106, in _row_as_tuple_getter
indexes = self._indexes_for_keys(keys)
[2022-05-06 16:45:00,122: WARNING/ForkPoolWorker-1] **AttributeError: '_NoResultMetaData' object has no attribute '_indexes_for_keys'**
[2022-05-06 16:45:00,122: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1799, in _execute_context
self.dialect.do_execute(
[2022-05-06 16:45:00,123: WARNING/ForkPoolWorker-2] File "/venv/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 717, in do_execute
cursor.execute(statement, parameters)
[2022-05-06 16:45:00,123: WARNING/ForkPoolWorker-2] **sqlalchemy.exc.DatabaseError: (psycopg2.DatabaseError) error with status PGRES_TUPLES_OK and no message from the libpq
[SQL: SELECT account.id AS account_id, account.username AS account_username, account.password AS account_password, account.created_at AS account_created_at, account.updated_at AS account_updated_at
FROM account]**
(Background on this error at: https://sqlalche.me/e/14/4xp6)
我的设置如下:
任务.py
@app.task
def run_logger_task():
try:
session = SessionMaker()
db = DBSession(session)
accounts = db.get_accounts() # calls self.session.query(Account).all()
for account in accounts:
.
.
.
finally:
db.close()
数据库.py
SQLALCHEMY_DATABASE_URL = f"postgresql://{db_username}:{db_password}@{db_host}/{db_name}"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionMaker = sessionmaker(autocommit=False, autoflush=False, bind=engine)
**Base.metadata.create_all(engine)** # Commenting this, fixes the error. But running it should be safe even if db tables already exist
模型.py
Base = declarative_base()
class Account(Base):
当我单独运行每个任务时,不会出现错误。那么,这是什么
在将 FastAPI 与 SQLModel(底层的 SQLAlchemy)一起使用时,我遇到了类似的问题,评论中的解决方案确实对我有用。发布答案以获得更多可见性:
从这段代码开始,我在运行 celery 任务时遇到错误。
sqlalchemy.exc.DatabaseError: (psycopg2.DatabaseError) error with status PGRES_TUPLES_OK and no message from the libpq
这是导致问题的代码。
from sqlmodel import Session, create_engine
from api import models
engine = create_engine(url="postgresql://postgres:secret@localhost/rssfeed", echo=True)
# Link user-defined SQL models
models.SQLModel.metadata.create_all(engine) # type: ignore
# Gets db session through context manager
def get_session() -> Session:
return Session(engine)
解决方法是简单地创建另一个引擎并将其传递给会话创建者。就这么简单!
from sqlmodel import Session, create_engine
from api import models
engine = create_engine(url="postgresql://postgres:secret@localhost/rssfeed", echo=True)
session_engine = create_engine(
url="postgresql://postgres:secret@localhost/rssfeed", echo=True
)
# Link user-defined SQL models
models.SQLModel.metadata.create_all(engine) # type: ignore
# Gets db session through context manager
def get_session() -> Session:
return Session(session_engine)