【问题标题】:How to use context manager with exceptions如何在异常情况下使用上下文管理器
【发布时间】:2016-03-31 13:28:39
【问题描述】:

我需要从电子邮件中读取文件附件。我想使用上下文管理器进行资源管理(应该关闭连接)

@contextmanager
def some_f():
    conn = None
    try:
        for _ in xrange(CONNECTION_ERRORS_MAX):
            try:
                conn = POP3(self.pop3_host)
                conn.user(self.pop3_user)
                conn.pass_(self.pop3_password)
                logger.debug('connected {}', conn.getwelcome())
                _, msg_ids, _ = conn.uidl()
                yield (
                    (msg_id, self.files_from_msg(conn, file_batch_id, msg_id))
                    for msg_id, file_batch_id in
                    (ul.split(' ') for ul in msg_ids)
                    if not self.is_ignored(file_batch_id, msg_id)
                )
            except socket.error as e:
                if e.errno == errno.ECONNREFUSED:
                    pass
                else:
                    raise e
    finally:
        if conn:
            conn.quit()

所以这个函数应该做的是尝试连接到电子邮件服务器,如果连接被拒绝,如果发生另一个套接字错误,则重试 n 次,然后重新启动它。如果重试尝试用尽,则重新引发连接被拒绝错误。消费者消费完所有文件后关闭连接。 现在它给出了生成器没有产生错误。

【问题讨论】:

  • 那是contextlib.contextmanager吗?
  • 如果您阅读the docs 中的contextmanager,您会看到管理器功能应该首先执行一些设置操作,然后让给“客户端”代码(即with 语句),然后执行一些清理; with 语句本质上是一种将代码夹在一些预定义的前后逻辑中的方式。在您的情况下,yield 语句位于 for-loop 内,这可能不是您想要的。
  • 您应该展示您打算如何使用该上下文管理器。

标签: python exception-handling contextmanager


【解决方案1】:

重组你的 try-except 子句,使其包含最少数量的事物。在except子句中,必要时可以continue,如果没有触发,则应从for循环中break

【讨论】:

    猜你喜欢
    • 2019-01-03
    • 2023-01-18
    • 2016-05-30
    • 2020-06-07
    • 1970-01-01
    • 2015-03-25
    • 2012-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多