我应该在 urllib.urlopen() 之后调用 close() 吗?
- 2025-03-20 08:48:00
- admin 原创
- 36
问题描述:
我是 Python 新手,正在阅读别人的代码:
后面应该urllib.urlopen()
跟urllib.close()
? 否则会泄漏连接,对吗?
解决方案 1:
该方法必须在的结果close
上调用,而不是像您所想的那样在模块本身上调用(正如您提到的- 它不存在)。urllib.urlopen
`urllib`urllib.close
最好的方法:不要使用x = urllib.urlopen(u)
etc,而是使用:
import contextlib
with contextlib.closing(urllib.urlopen(u)) as x:
...use x at will here...
即使出现异常,该with
语句和上下文管理器也将确保正确关闭。closing
解决方案 2:
就像@Peter说的,超出范围打开的URL将被垃圾收集。
但是,还请注意,在 CPython 中URLopener
定义:
def __del__(self):
self.close()
这意味着当该实例的引用计数达到零时,__del__
将调用其方法,因此其close
方法也将被调用。引用计数达到零的最“正常”方式是让实例超出范围,但没有什么严格阻止您提前显式调用del x
(但它不会直接调用,__del__
而只是将引用计数减一)。
明确关闭您的资源当然是一种好的做法 - 特别是当您的应用程序面临使用过多资源的风险时 - 但是如果您不做任何奇怪的事情(例如维护(循环?)对不再需要的实例的引用),Python会自动为您清理。
解决方案 3:
严格来说,这是真的。但在实践中,一旦(if)urllib
超出范围,连接将被自动垃圾收集器关闭。
解决方案 4:
使用IronPython时,您基本上需要明确关闭连接。超出范围时自动关闭依赖于垃圾收集。我遇到过一种情况,垃圾收集运行时间太长,导致 Windows 用完了套接字。我以高频率轮询网络服务器(即 IronPython 和连接允许的最高频率,~7Hz)。我可以看到 PerfMon 上的“已建立连接”(即正在使用的套接字)不断增加。解决方案是在每次调用后调用。gc.collect()
`urlopen`
解决方案 5:
urllib.request 模块使用 HTTP/1.1 并
Connection:close
在其 HTTP 请求中包含标头。
它来自官方文档,你可以在这里查看。
扫码咨询,免费领取项目管理大礼包!