【问题标题】:Python ftplib: How to correctly release connection object?Python ftplib:如何正确释放连接对象?
【发布时间】:2017-09-26 14:31:38
【问题描述】:

我见过这样的代码(Python 3 代码):

import ftplib
from contextlib import closing

with closing(ftplib.FTP()) as ftp:

有必要使用closing 方法吗?在一个有趣的answer 中,我们可以读到在数据库连接对象中,上下文管理器的__exit__ 方法不会关闭连接(至少对于SQLite 不会),而是提交一个事务。因此,必须使用closing 方法。

Python 的 FTP 类怎么样?

查看Python ftplib的sources,可以发现:

# Context management protocol: try to quit() if active
def __exit__(self, *args):
    if self.sock is not None:
        try:
            self.quit()
        except (OSError, EOFError):
            pass
        finally:
            if self.sock is not None:
                self.close()

quit 方法被调用,因此我认为我们不必为 Python 3 使用closing 方法。所以我们可以只使用:

with (ftplib.FTP()) as ftp:

由于 Python 2 中缺少 __exit__ 方法,因此 Python 2 代码需要 closing

这对吗?

【问题讨论】:

  • 你已经回答了你自己的问题:) 正如你所说,在 Python2 中。既没有__enter__ 函数也没有__exit__ 函数,因为上下文句柄在进入或退出时不会做任何事情,除了在你的情况下分配变量ftp。所以这是一个继承和向后兼容的合规性事情。如果您对成为一名倒退忍者不感兴趣,可以跳过它。
  • @Torxed 由于互联网上充斥着不正确的代码示例(我知道在许多一次性的小脚本中,您不需要为这些细节烦恼)一个很容易混淆,所以我想要确认。
  • 这是一个非常好的问题 :) 我写了一个更长的答案,以防人们偶然发现这个问题。

标签: python ftp ftplib


【解决方案1】:

您确实回答了大部分问题。
根据 cmets 中的讨论,这是一个合理的问题,因为互联网“充斥着不正确的代码示例”

为了澄清我的简短回答,这是一个传统问题,Python3 代码在 Python2 上无法按预期执行。因此,互联网上的(好)示例有望包括对在 Python2 中运行代码的危险性的解释。或者他们将使代码向后兼容,并进行一些小的修改。

这是这样一个实例,当代码在 Python2 上运行时,closing() 用于模拟来自 Python3 的新函数。

Python2 (ftplib) 没有 __enter____exit__ 函数,因此使上下文句柄“无用”(除了使其向前兼容、更易于阅读 IMO 并且还将调用分配给变量,在本例中为 ftp)。
为了让它没用,作者在调用周围使用了closing(),以根据 Python3 自动关闭。

如果您真正使用 Python3,这是多余的,并且可能会减慢您的代码速度(非常少)。如果您不希望向后兼容,您可以跳过那段特定的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多