You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何扩展psycopg2 cursor类的__iter__方法实现迭代后自动关连接?

问题分析与解决方案

递归错误原因

你遇到的RecursionError是因为psycopg2的cursor类的__iter__方法返回的是游标实例本身(self),而非独立迭代器。当你在子类中用yield from super().__iter__()时,super().__iter__()返回的是你的AutoCloseCur实例,会再次触发子类的__iter__方法,形成无限递归。

正确的自定义游标实现

你需要重写__next__方法而非__iter__,通过捕获StopIteration异常判断迭代是否耗尽,再执行关闭操作:

class AutoCloseCur(psycopg2.extensions.cursor):
    def __next__(self):
        try:
            # 调用父类的__next__获取下一行数据
            return super().__next__()
        except StopIteration:
            # 迭代耗尽,关闭游标和连接
            self.close()
            self.connection.close()
            # 必须重新抛出StopIteration,否则迭代器无法正常终止
            raise

你的疑问解答

  1. 继承类是否正确?
    是的,psycopg2.extensions.cursor就是psycopg2游标类的正确基类,继承它没有问题。

  2. 是否需要重写其他魔法方法?
    针对迭代场景,重写__next__就足够。如果你的代码中还有直接调用fetchone()、fetchmany()等方法的场景,可以封装这些方法,在返回空结果时执行关闭操作,但迭代场景下无需额外重写其他方法。

  3. psycopg2是否有内置功能?
    psycopg2本身没有提供迭代耗尽自动关闭连接的内置功能,但官方推荐使用**上下文管理器(with语句)**管理连接和游标生命周期:

    with psycopg2.connect(...) as conn:
        with conn.cursor(name='server-side-cursor') as cur:
            cur.execute("SELECT ...")
            for row in cur:
                # 处理数据
    

    上下文管理器会在代码块结束时自动关闭游标和连接,无需手动调用close()。不过如果你更倾向于自定义游标类的方式,前面的实现完全可行。

注意:如果多个游标共享同一个数据库连接,迭代耗尽后关闭连接会影响其他游标,这种场景下建议不要在游标中关闭连接,而是单独管理连接的生命周期。

内容的提问来源于stack exchange,提问作者Shiva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 09:42:38