2017-09-26 115 views
1

我见过这样的代码(Python 3的代码):Python ftplib:如何正确释放连接对象?

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方法被调用,因此我认为我们不必使用closing方法为Python 3.因此,我们可以只使用:

with (ftplib.FTP()) as ftp: 

__exit__由于方法在Python 2丢失,closing是必要的Python 2代码。

这是正确的吗?

+1

你已经回答了你自己的问题:)在Python2中,就像你说的。没有'__enter__'函数或'__exit__'函数,那里的上下文句柄在进入或退出时不会做任何事情,除非在你的情况下分配变量'ftp'。所以这是一个继承和向后兼容的遵从性事情。如果你不想成为逆向忍者,你可以跳过它。 – Torxed

+0

@Toxxed由于互联网上充斥着不正确的代码示例(我明白,在很多一次性小脚本中,您不需要打扰这些细节),所以很容易混淆,所以我想要确认。 –

+0

问这是一个完全正确的问题:)我写了一个更长的答案,以防人们在这个问题上磕磕绊绊。 – Torxed

回答

1

你的确大部分都回答了你自己的问题。
并按照在评论中讨论的那样,这是一个合法的问题,因为互联网是“充满了不正确的代码示例”

要澄清我的答案很简单,这是一个传统问题,即在Python2预期Python3代码不会执行。因此,互联网上的(好的)例子有望包含对在Python2中运行代码的危险性的解释。或者他们会通过小的修改使代码向后兼容。

这是当代码上运行Python2 closing()用于从Python3模拟新的功能这样的实例。

Python2(ftplib)没有__enter____exit__函数,因此呈现上下文句柄“无用”(除了使它向前兼容,更容易读取IMO并且它还将该调用分配给变量)这种情况下ftp)。
为了避免这种情况发生,编写者在调用时使用了closing()来根据Python3获取自动闭包。

如果souly使用Python3是,这是多余的,可能会减慢你的代码(极少)。如果你不想向后兼容,那么你可以跳过那段代码。