72

我是 Python 新手,正在阅读别人的代码:

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

4

5 回答 5

105

close必须在 的结果上调用该方法urllib.urlopen而不是urllib您正在考虑的模块本身上调用该方法(正如您所提到的urllib.close——它不存在)。

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

import contextlib

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

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

于 2009-10-05T22:22:17.130 回答
14

就像@Peter 所说,超出范围的打开 URL 将有资格进行垃圾收集。

但是,还要注意urllib.py定义:

 def __del__(self):
        self.close()

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

显式关闭资源肯定是一种很好的方式——尤其是当你的应用程序冒着使用过多资源的风险时——但是如果你不做任何有趣的事情,比如维护(循环?)引用,Python自动为你清理。到您不再需要的实例。

于 2009-10-05T22:24:08.660 回答
6

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

于 2009-10-05T22:07:57.997 回答
1

使用IronPython时,您基本上确实需要明确关闭您的连接。超出范围的自动关闭依赖于垃圾收集。我遇到了一种情况,即垃圾收集没有运行很长时间,以至于 Windows 用完了套接字。我以高频率轮询网络服务器(即与 IronPython 一样高,并且连接允许,~7Hz)。我可以看到“已建立的连接”(即使用中的套接字)在 PerfMon 上不断上升。解决方案是在每次调用.gc.collect()urlopen

于 2019-03-12T15:38:24.387 回答
0

urllib.request 模块使用 HTTP/1.1 并Connection:close在其 HTTP 请求中包含标头。

它来自官方文档,你可以在这里查看

于 2021-01-01T01:02:05.573 回答