【问题标题】:should I call close() after urllib.urlopen()?我应该在 urllib.urlopen() 之后调用 close() 吗?
【发布时间】:2021-11-08 05:47:46
【问题描述】:

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

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

【问题讨论】:

    标签: python urllib


    【解决方案1】:

    close 方法必须在 urllib.urlopenresult 上调用,而不是urllib 模块本身上调用,正如您正在考虑的那样(当您提及urllib.close——不存在)。

    最好的方法:代替x = urllib.urlopen(u)等,使用:

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

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

    【讨论】:

    • data = urllib2.urlopen('url').read()这样的事情怎么样
    • 在 Python 3 中,添加了对 with 语句的直接支持。使用 urllib.urlopen(u) 作为 x: ...
    • 为什么python3 doc 在这个(咳咳)上下文中仍然提到contextlib.closing
    • @ÉricAraujo:在 python 3 中,urllib.urlopen 根本不存在。
    • 它被移动到一个新的子模块 urllib.request:docs.python.org/3/library/…
    【解决方案2】:

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

    不过,还要注意urllib.py 定义:

     def __del__(self):
            self.close()
    

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

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

    【讨论】:

    • 然而,有可能超出垃圾收集器——我有过创建文件句柄比关闭它们更快的情况[但是显式的 gc.collect() 调用或 @ 987654329@,收拾东西]。
    【解决方案3】:

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

    【讨论】:

    • 这在 Python 的某些实现中是正确的,但是 Python 语言不保证对象一旦超出范围就会关闭。参看。 jython
    • @gnibbler 这个答案的作者没有说它会发生只要它就会发生。
    • @Piotr,但如果我有一个循环打开 url 并且 GC 没有足够快地获取它们,程序可能会崩溃。这是一种非常草率的做事方式,不属于生产代码。
    • no-op GC(即永远不会运行的 GC)对 Python 完全有效。您无法保证 GC 将永远运行。而gc.disable 可以在大多数 Python 实现中禁用 GC。
    • 在 GC 进行任何清理之前,我设法用完了可用的连接。所以是的,如果您不想突然发现连接丢失,您应该打电话关闭。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      来自官方文档,您可以查看here

      【讨论】:

        猜你喜欢
        • 2015-03-28
        • 2011-11-23
        • 2010-10-13
        • 2013-01-02
        • 1970-01-01
        • 2015-08-10
        • 2018-07-02
        • 1970-01-01
        相关资源
        最近更新 更多