我编写了一个Python应用程序,该应用程序使用SQLAlchemy连接到Postgres DB。 engine
和session
在db.py
engine = create_engine(URL(**settings.DATABASE))
session = scoped_session(sessionmaker(bind=engine))
大多数数据库操作在service.py
中,它们从session
导入db.py
from app.db import engine, session
def get_door_ids():
result = session.query(ControllerDetail.door_id).distinct().all()
ids = [c[0] for c in result]
return ids
def get_last_health_cd(door_id):
result = session.query(ControllerDetail.door_health_cd).filter(ControllerDetail.door_id == door_id).order_by(ControllerDetail.etl_insert_ts.desc()).first()
return result[0]
现在一切正常,但是问题是我需要每隔几分钟重复运行同一件事。所以我的主模块中有以下代码:
try:
while True:
run_task()
time.sleep(120)
except KeyboardInterrupt:
print('Manual break by user')
数据库每分钟空闲连接超时。因此,每当该过程进入睡眠状态超过1分钟时,我都会出错。
psycopg2.InternalError: terminating connection due to idle-in-transaction timeout
SSL connection has been closed unexpectedly
我想知道是否有一种方法可以关闭会话并在time.sleep(120)
之后重新打开它,这样它就不会超时。也许在主模块中,我从session
导入db
作为全局变量,并以某种方式将其传递给services
中的方法。我怎么做?我无法从session
而不是services
导入main
中的db
,因为main
从services
导入了函数。
答案 0 :(得分:1)
首先,您应该通过提交/回滚来及时结束事务。 Closing会话也将隐式回滚。如果是作用域会话,removing将关闭该会话(并从注册表中删除该会话)。总而言之,"When do I construct a Session, when do I commit it, and when do I close it?"是很好的阅读内容。
一些人可能会感到惊讶的是,Session
在您开始与数据库通信后就开始了新的事务。然后,您的工作就是结束该交易。没有看到run_task()
的实际作用,很难说哪个部分应该处理会话的生命周期,但是可以肯定地说,如果任务每隔几分钟运行一次,则您不应将事务挂那么长时间。>
答案 1 :(得分:0)
增加超时时间
create_engine(URL(**settings.DATABASE), connect_args={'connect_timeout': 10})
session.close()