Python:如何确保类实例清除资源

问题描述 投票:2回答:1

[首先让我承认,这里已经存在不错的讨论:How do I correctly clean up a Python object?

[我正在尝试提高当前示意性地这样的代码的效率:

import psycopg2

class StuffHandler:
    def __init__(self, db_credentials):
        self.db_credentials = db_credentials
    def handle(self, stuff):
        try:
            with psycopg2.connect(self.db_credentials) as conn:
                with conn.cursor() as cursor:
                    cursor.execute( < write stuff to database > )
        except psycopg2.DataError as e:
            logger.error(e)
        finally:
            conn.close()

如您所见,这是正确的,但是每次都不必要地打开和关闭数据库连接,这是我要改善的。

上面的代码由应用程序以下列方式示意性地使用:

h = StuffHandler(db_credentials)
my_obj.set_stuff_handler(h)

我希望该对象保持长期连接,示意上我认为它应该像这样工作

import psycopg2

class Handler:
    def __init__(self, db_credentials):
        self.conn = psycopg2.connect(db_credentials)
    def handle(self, stuff):
        # TODO: check that connection is still alive, but those are
        # details don't matter for this discussion
        try:
            with self.conn.cursor() as cursor:
                cursor.execute( < write stuff to database > )
        except psycopg2.DataError as e:
            logger.error(e)

问题是:在Python中,如何正确清理资源?这包括关闭连接,还包括一些类似的操作,例如是否要添加缓冲区,刷新缓冲区等。

根据标记为正确且更新得多的答案https://stackoverflow.com/a/865272/12595391,答案为:添加方法__enter____exit__,以便可以将该类用作上下文。我想这意味着:

def __enter__(self):
    return self
def __exit__(exc_type, exc_value, traceback):
    self.conn.close()

所以现在我的问题变成了:如果我不想使用上下文该怎么办?如果我不想做怎么办

with StuffHandler(db_credentials) as h:
    my_obj.set_stuff_handler(h)

但是我不想触摸应用程序代码?

[在上述问题中,此答案中描述了一种替代方法:https://stackoverflow.com/a/41627098/12595391,其中他们建议使用atexit.register()注册清除方法。这不是更适合我的情况吗?这种方法的缺点是什么?评论员@hlongmore似乎提到了一个缺点,但我不太明白他的意思。

感谢您的帮助。

python database code-cleanup
1个回答
1
投票

您可以尝试使用__del__,以为最好使用上下文管理器

import psycopg2

class Handler:
    def __init__(self, db_credentials):
        self.conn = psycopg2.connect(db_credentials)
    def handle(self, stuff):
        # TODO: check that connection is still alive, but those are
        # details don't matter for this discussion
        try:
            with self.conn.cursor() as cursor:
                cursor.execute( < write stuff to database > )
        except psycopg2.DataError as e:
            logger.error(e)
    def __del__():
        self.conn.close()

[当对象被垃圾回收时调用,What is the __del__ method, How to call it?

© www.soinside.com 2019 - 2024. All rights reserved.