我使用Cherrypy构建了WSGI应用程序和SQLAlchemy Core(仅用于连接池和执行文本SQL语句),在Python 3.2之上构建了一些自定义Web框架。
我正在使用的版本:
对于每个请求,都使用sqlalchemy.engine.base.Engine
的{{1}}方法从池中检索数据库连接。请求处理程序完成后,使用connect
方法关闭连接。伪代码例如:
close
其中with db.connect() as db:
handler(db)
是上下文管理器定义如下:
db.connect()
我希望这是执行此任务的正确做法。它一直有效,直到页面处理程序的内容变得更复杂。
我的行为很奇怪。由于未知原因,连接有时会在处理程序完成工作之前关闭。但不是每一次!
通过观察,只有在连续快速发出请求时才会发生这种情况。如果我在请求之间进行小暂停,则连接未关闭且请求成功完成。但无论如何,每次都不会发生这种情况。我没有在请求的失败/成功中找到更具体的模式。
我发现我的上下文管理器没有关闭连接。它已经关闭了。
我的问题: 如何确定何时,为什么以及通过什么代码关闭我的连接?
我试过调试。我在@contextmanager
def connect(self):
conn = self.engine.connect()
try:
yield conn
finally:
conn.close()
的{{1}}方法上设置了断点,但在达到此代码之前连接已关闭。这很奇怪。
我将不胜感激任何提示或帮助。
* 编辑* zzzeek要求的信息:
“连接关闭”的症状:
很抱歉没有澄清此事。 sqlalchemy.engine.base.Connection
已关闭。
在处理程序中,我调用close
的{{1}}方法从数据库中获取数据(select语句)。我可以说sqlalchemy.engine.Connection
已关闭,因为我在调用execute之前检查它是sqlalchemy.engine.base.Connection
属性。
我可以在这里发布回溯,但只有你可能会在其中看到的是在我的数据库包装器库中执行之前引发了异常(因为连接已关闭)。
如果我删除此检查(并执行execute
方法),SQLAlchemy会引发此异常:http://pastebin.com/H6052yca
关于zzzeek提到的确定性问题。我必须道歉。经过多次观察,情况略有不同。
这是如何调用错误的确切步骤:
sqlalchemy.engine.Connection
我使用的默认SQLAlchemy池类与pool_size = 5。
我知道当你没有实际代码时,你无法创造奇迹。但不幸的是,我不能分享它。是否有调试此类错误的最佳做法?或者唯一的选择是逐步调试并尝试弄清楚?
另一个观察结果:
当我在调试器(WingIDE)中启动服务器时,我无法提起错误。可能是因为调试器在解释代码时速度太慢,在处理第二个请求(RequestB)之前,连接以某种方式被“修复”。
答案 0 :(得分:3)
经过一整天的调试。我发现了问题。
不幸的是,它直接与SQLAlchemy无关。所以应该删除这个问题。但你们试图帮助我,所以我会回答我自己的问题。也许,有一天有人会发现这有用。
基本上,错误是由我的自定义发布/订阅方法引起的,这种方法在多线程环境中没有很好地发挥作用。
我尝试逐行踩代码...这不起作用(正如我在问题中描述的那样)。所以我开始生成非常详细的日志记录。
即便如此,一切看起来都很正常,直到我注意到崩溃前几行,模型中引用的Connection对象的地址发生了变化。这实际上意味着某个东西将另一个Connection对象分配给模型,并且该连接对象已经关闭。
所以教训是。当一切看起来都正确时,打印/记录有问题的对象的repr()。
感谢评论员的时间。