我应该在 urllib.urlopen()之后调用 close()吗?

我是 Python 的新手,读了别人的代码:

urllib.urlopen()后面应该跟着 urllib.close()吗? 否则,会泄漏连接,对吗?

55478 次浏览

严格来说,这是真的。但实际上,一旦(如果) urllib超出范围,连接将由自动垃圾收集器关闭。

在您考虑的时候,必须在 urllib.urlopen结果上调用 close方法,在 urllib模块本身上调用 没有方法(正如您提到的 urllib.close——它并不存在)。

最佳方法: 不使用 x = urllib.urlopen(u)等,而是使用:

import contextlib


with contextlib.closing(urllib.urlopen(u)) as x:
...use x at will here...

with语句和 closing上下文管理器将确保即使存在异常也能正确关闭。

正如@Peter 所说,范围外打开的 URL 将有资格进行垃圾收集。

不过,请注意 在 CPython URLopener中定义:

 def __del__(self):
self.close()

这意味着 当该实例的引用计数达到零时,它的 __del__方法将被调用,因此它的 close方法也将被调用。引用计数达到零的最“正常”的方法是简单地让实例超出作用域,但是没有什么严格地阻止您尽早使用显式的 del x(然而它并不直接调用 __del__,而只是将引用计数减少一)。

显式地关闭资源当然是一种很好的风格——特别是当您的应用程序冒着使用过多资源的风险时——但是如果您不做任何有趣的事情,比如维护(循环?) ,Python 威尔会自动为您清理资源对不再需要的实例的引用。

在使用 铁蟒时,基本上 需要显式关闭连接。超出范围时的自动关闭依赖于垃圾回收。我遇到了这样一种情况: 垃圾收集没有运行太长时间,以至于 Windows 的套接字用完了。我在高频率轮询一个网络服务器(例如,高达 IronPython 和连接将允许,~ 7Hz)。我可以看到“已建立的连接”(即正在使用的套接字)在 PerfMon 上不断增加。解决方案是在每次调用 urlopen之后调用 gc.collect()

Request 模块使用 HTTP/1.1,并在其 HTTP 请求中包含 Connection:close头。

这是官方文件,你可以检查它 给你