首页 > 解决方案 > python GC是否保证是一个引用计数垃圾收集器

问题描述

对于我的存储库类,我在函数需要时创建与数据库的连接(如果没有)。如果不是无,我正在使用__del__关闭连接。该对象保证是短暂的。

我意识到我依赖 Ref 计数来尽快关闭连接。我需要连接成为课堂上的一个字段,因为我正在做一个select for update. 我阅读的默认 python gc 确实至少计算了 CPython 实现。但是 pypy 实现有许多不同类型的垃圾收集器。靠 ref 计数 gc 尽快关闭连接可以吗?或者我应该编写一个单独的函数并确保使用 try finally 块关闭连接?

该类仅包含连接字段和两个函数,一个用于锁定数据库中的表并选择值,另一个用于更新它们。

这是我目前的实现:

class ReserveRepository:
    def __init__(self):
        self.conn = None

    def select(self):
        cur = None
        try:
            self.conn = psycopg2.connect(config.DATABASE_URL)
            cur = self.conn.cursor()

            cur.execute('lock table sometable in ACCESS EXCLUSIVE mode')

            cur.execute('select id from sometable where condition')

            return list(map(lambda x: x[0]))
        finally:
            if cur is not None:
                cur.close()

    def update_quantities(self, id):
        cur = None
        try:
            if self.conn is None:
                self.conn = psycopg2.connect(config.DATABASE_URL)

            cur = self.conn.cursor()

            cur.execute('update sometable set column1 = value where id = %s', (id,))
            self.conn.commit()
            return reservation_id
        finally:
            if cur is not None:
                cur.close()

    def __del__(self):
        if self.conn is not None:
            self.conn.close()
            self.conn = None

标签: pythongarbage-collectionpypy

解决方案


tldr; 答案是否定的。据我了解,Pypy 没有实现引用计数。为了证明这一点,我做了这个简单的程序:

class Test:
    def __init__(self):
        print('__init__')

    def __del__(self):
        print('__del__')

t = Test()
print(t)

CPython 3.8.2 上的输出是:

__init__
<__main__.Test object at 0x7f6e3bc13dc0>
__del__

但是,Pypy 7.3.1 (Python 3.6.9) 上的输出是

__init__
<__main__.Test object at 0x00007f58325dfe88>

__del__函数未被调用。


推荐阅读