gpt4 book ai didi

python - 手动调用 __enter__ 和 __exit__

转载 作者:IT老高 更新时间:2023-10-28 20:47:30 25 4
gpt4 key购买 nike

我用谷歌搜索了 calling __enter__ manually但没有运气。所以让我们假设我有 MySQL 连接器类,它使用 __enter____exit__ 函数(最初与 with 语句一起使用)连接/断开与数据库的连接。

让我们有一个使用其中 2 个连接的类(例如用于数据同步)。 注意:这不是我的真实场景,但它似乎是最简单的例子

让它们一起工作的最简单方法是这样的类:

class DataSync(object):

def __init__(self):
self.master_connection = MySQLConnection(param_set_1)
self.slave_connection = MySQLConnection(param_set_2)

def __enter__(self):
self.master_connection.__enter__()
self.slave_connection.__enter__()
return self

def __exit__(self, exc_type, exc, traceback):
self.master_connection.__exit__(exc_type, exc, traceback)
self.slave_connection.__exit__(exc_type, exc, traceback)

# Some real operation functions

# Simple usage example
with DataSync() as sync:
records = sync.master_connection.fetch_records()
sync.slave_connection.push_records(records)

Q:这样手动调用__enter__/__exit__可以吗(有什么问题吗)?

Pylint 1.1.0 没有对此发出任何警告,我也没有找到任何关于它的文章(谷歌链接在开头)。

那么调用呢:

try:
# Db query
except MySQL.ServerDisconnectedException:
self.master_connection.__exit__(None, None, None)
self.master_connection.__enter__()
# Retry

这是一种好/坏的做法吗?为什么?

最佳答案

你的第一个例子不是一个好主意:

  1. 如果 slave_connection.__enter__ 抛出异常会发生什么:

    • master_connection 获取其资源
    • slave_connection 失败
    • DataSync.__enter__ 传播异常
    • DataSync.__exit__ 不运行
    • master_connection 永远不会被清理!
    • 坏事的可能性
  2. 如果 master_connection.__exit__ 抛出异常会怎样?

    • DataSync.__exit__提前完成
    • slave_connection 永远不会被清理!
    • 坏事的可能性

contextlib.ExitStack 可以在这里提供帮助:

def __enter__(self):
with ExitStack() as stack:
stack.enter_context(self.master_connection)
stack.enter_context(self.slave_connection)
self._stack = stack.pop_all()
return self

def __exit__(self, exc_type, exc, traceback):
self._stack.__exit__(self, exc_type, exc, traceback)

问同样的问题:

  1. 如果 slave_connection.__enter__ 抛出异常会发生什么:

    • with block 退出,stack 清理 master_connection
    • 一切正常!
  2. 如果 master_connection.__exit__ 抛出异常会怎样?

    • 没关系,slave_connection会在调用之前清理干净
    • 一切正常!
  3. 好的,如果 slave_connection.__exit__ 抛出异常会怎样?

    • ExitStack 确保调用 master_connection.__exit__ 无论从属连接发生什么
    • 一切正常!

直接调用 __enter__ 并没有什么问题,但是如果需要在多个对象上调用它,请确保正确清理!

关于python - 手动调用 __enter__ 和 __exit__,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26635684/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com