【问题标题】:What are the differences between the urllib, urllib2, urllib3 and requests module?urllib、urllib2、urllib3 和 requests 模块有什么区别?
【发布时间】:2011-01-02 08:19:00
【问题描述】:

在 Python 中,urlliburllib2urllib3requests 模块之间有什么区别?为什么有三个?他们似乎做同样的事情......

【问题讨论】:

  • 应该更新这个问题以澄清 Python 3 中的 urllib 是另一种选择,以各种方式清理。但值得庆幸的是,官方文档还指出“建议将 Requests 包用于更高级别的 HTTP 客户端接口。21.6. urllib.request — Extensible library for opening URLs — Python 3.6.3 documentation
  • 遗憾的是,我没有看到任何答案告诉我urllib3 是什么以及urllib3 与官方urllib 模块有何不同。
  • 可能值得一提 httpx — 较新的 requests-backwords 兼容异步库。

标签: python python-requests urllib2 urllib python-2.x


【解决方案1】:

我知道已经说过了,但我强烈推荐requests Python 包。

如果你用过python以外的语言,你可能会觉得urlliburllib2好用,代码不多,功能强大,我以前就是这么想的。但是requests 软件包非常有用且简短,以至于每个人都应该使用它。

首先,它支持完全宁静的 API,并且非常简单:

import requests

resp = requests.get('http://www.mywebsite.com/user')
resp = requests.post('http://www.mywebsite.com/user')
resp = requests.put('http://www.mywebsite.com/user/put')
resp = requests.delete('http://www.mywebsite.com/user/delete')

无论是 GET / POST,您都不必再次对参数进行编码,它只需将字典作为参数即可:

userdata = {"firstname": "John", "lastname": "Doe", "password": "jdoe123"}
resp = requests.post('http://www.mywebsite.com/user', data=userdata)

此外,它甚至还有一个内置的 JSON 解码器(我知道json.loads() 写的不多,但这确实很方便):

resp.json()

或者,如果您的响应数据只是文本,请使用:

resp.text

这只是冰山一角。这是请求站点的功能列表:

  • 国际域名和网址
  • 保持活动和连接池
  • 具有 Cookie 持久性的会话
  • 浏览器式 SSL 验证
  • 基本/摘要式身份验证
  • 优雅的键/值 Cookie
  • 自动解压
  • Unicode 响应正文
  • 分段文件上传
  • 连接超时
  • .netrc 支持
  • 列表项
  • Python 2.7、3.6—3.9
  • 线程安全。

【讨论】:

【解决方案2】:

这是我对各种“urllib”之间关系的理解:

在 Python 2 标准库中同时存在两个 HTTP 库。尽管名称相似,但它们并不相关:它们具有不同的设计和不同的实现。

  • urllib 是最初的 Python HTTP 客户端,添加到 Python 1.2 的标准库中。 urllib 的早期文档可以在 Python 1.4 中找到。

  • urllib2 是一个功能更强大的 HTTP 客户端 added in Python 1.6,旨在替代 urllib

    urllib2 - 新的和改进但不兼容的 urllib 版本(仍处于试验阶段)。

    urllib2 的早期文档可以在 Python 2.1 中找到。

Python 3 标准库有一个 new urllib,它是旧模块的合并/重构/重写版本。

urllib3 是第三方包(即不在 CPython 的标准库中)。尽管有这个名字,但它与标准库包无关,将来也不打算将它包含在标准库中。

最后,requests 在内部使用了urllib3,但它旨在提供更易于使用的 API。

【讨论】:

    【解决方案3】:

    我认为所有的答案都很好。但是关于 urllib3 的细节较少。urllib3 是一个非常强大的 Python 的 HTTP 客户端。 为了安装以下两个命令都可以,

    urllib3

    使用点子,

    pip install urllib3
    

    或者您可以从 Github 获取最新代码并使用它们进行安装,

    $ git clone git://github.com/urllib3/urllib3.git
    $ cd urllib3
    $ python setup.py install
    

    那么你准备好了,

    只需使用导入 urllib3,

    import urllib3
    

    在这里,您需要一个 PoolManager 实例来发出请求,而不是直接创建连接。这将为您处理连接池和线程安全。还有一个 ProxyManager 对象用于通过 HTTP/HTTPS 代理路由请求 在这里您可以参考文档。 示例用法:

    >>> from urllib3 import PoolManager
    >>> manager = PoolManager(10)
    >>> r = manager.request('GET', 'http://google.com/')
    >>> r.headers['server']
    'gws'
    >>> r = manager.request('GET', 'http://yahoo.com/')
    >>> r.headers['server']
    'YTS/1.20.0'
    >>> r = manager.request('POST', 'http://google.com/mail')
    >>> r = manager.request('HEAD', 'http://google.com/calendar')
    >>> len(manager.pools)
    2
    >>> conn = manager.connection_from_host('google.com')
    >>> conn.num_requests
    3
    

    正如urrlib3 文档中所述,urllib3 带来了 Python 标准库中缺少的许多关键功能。

    • 线程安全。
    • 连接池。
    • 客户端 SSL/TLS 验证。
    • 使用多部分编码的文件上传。
    • 重试请求和处理 HTTP 重定向的帮助程序。
    • 支持 gzip 和 deflate 编码。
    • 对 HTTP 和 SOCKS 的代理支持。
    • 100% 的测试覆盖率。

    请按照用户指南了解更多详细信息。

    requests

    requests 在后台使用urllib3,使创建requests 和检索数据变得更加简单。 一方面,keep-alive 是 100% 自动的,而 urllib3 不是。它还具有事件挂钩,可在触发事件时调用回调函数,例如接收响应 在requests 中,每种请求类型都有自己的功能。因此,您无需创建连接或池,而是直接获取 URL。


    使用 pip 安装 requests 只需运行

    pip install requests

    或者你可以从源代码安装,

    $ git clone git://github.com/psf/requests.git
    $ cd requests
    $ python setup.py install
    

    那么,import requests

    这里可以参考官方documentation, 有关会话对象、SSL 验证和事件挂钩等高级用法,请参阅此url

    【讨论】:

    • 感谢您的回答。我来这里是因为我看过urllib3,但不知道该用它还是requests。现在,我对如何做出该决定感到了解。接受的答案对requests 进行了很好的细分,但并未将其与其他选项区分开来。
    • 是的,我也是来这里寻找 Requests、urllib、urllib2 和 urllib3 之间的差异,并对接受的答案感到不满意。应添加此说明或至少将其链接到已接受的答案。谢谢。
    • 如果您受到公司代理的困扰,请知道请求模块很乐意接受环境变量 http_proxy、https_proxy、no_proxy。 urllib3 模块忽略环境变量;要通过代理发送查询,您必须创建 ProxyManager 的实例而不是 PoolManager。
    【解决方案4】:

    urlliburllib2 都是 Python 模块,它们执行 URL 请求相关的东西,但提供不同的功能。

    1) urllib2 可以接受一个 Request 对象来设置一个 URL 请求的头部,urllib 只接受一个 URL。

    2) urllib 提供了urlencode 方法,用于生成GET 查询字符串,urllib2 没有这个功能。这也是为什么 urllib 经常和 urllib2 一起使用的原因之一。

    Requests - Requests 是一个用 Python 编写的简单易用的 HTTP 库。

    1) Python Requests 会自动对参数进行编码,因此您只需将它们作为简单参数传递,这与 urllib 不同,您需要使用方法 urllib.encode() 对参数进行编码在通过它们之前。

    2) 它自动将响应解码为 Unicode。

    3) Requests 还具有更方便的错误处理。如果您的身份验证失败,urllib2 将引发 urllib2.URLError,而 Requests 将返回一个正常的响应对象,如预期的那样。您只需通过布尔值 response.ok

    查看请求是否成功

    【讨论】:

    • urllib3 呢?
    • @PirateApp requests 建立在urllib3 之上。我认为直接使用 urllib3 的代码可以更有效,因为它可以让你重用会话,而请求(至少请求 2,每个人都使用的那个)为每个请求创建一个,但不要引用我的话。两者都不是标准库的一部分 (yet)
    【解决方案5】:

    我发现上述答案中缺少的一个关键点是 urllib 返回 <class http.client.HTTPResponse> 类型的对象,而 requests 返回 <class 'requests.models.Response'>

    因此,read() 方法可以与urllib 一起使用,但不能与requests 一起使用。

    附: :requests 已经拥有如此多的方法,几乎​​不需要像read() 那样的方法;>

    【讨论】:

      【解决方案6】:

      获取一个url的内容:

      try: # Try importing requests first.
          import requests
      except ImportError: 
          try: # Try importing Python3 urllib
              import urllib.request
          except AttributeError: # Now importing Python2 urllib
              import urllib
      
      
      def get_content(url):
          try:  # Using requests.
              return requests.get(url).content # Returns requests.models.Response.
          except NameError:  
              try: # Using Python3 urllib.
                  with urllib.request.urlopen(index_url) as response:
                      return response.read() # Returns http.client.HTTPResponse.
              except AttributeError: # Using Python3 urllib.
                  return urllib.urlopen(url).read() # Returns an instance.
      

      很难为响应编写 Python2 和 Python3 以及 request 依赖项代码,因为它们 urlopen() 函数和 requests.get() 函数返回不同的类型:

      • Python2 urllib.request.urlopen() 返回一个 http.client.HTTPResponse
      • Python3 urllib.urlopen(url) 返回一个instance
      • 请求request.get(url) 返回requests.models.Response

      【讨论】:

        【解决方案7】:

        只是为了补充现有答案,我没有看到有人提到 python 请求不是本机库。如果您可以添加依赖项,那么 requests 就可以了。但是,如果您试图避免添加依赖项,则 urllib 是一个本机 Python 库,您已经可以使用它。

        【讨论】:

        • 没错,如果你想避免添加任何依赖,urllib 是可用的。但请注意,即使是Python official documentation 也推荐了 requests 库:“建议将 Requests 包用于更高级别的 HTTP 客户端接口。”
        • @hlongmore 当然,大多数人不想处理低级别的 urllib,而 Requests 库提供了很好的抽象级别。这就像在盒子里使用煎饼混合物而不是从头开始制作。优点和缺点。
        【解决方案8】:

        一个相当大的区别是将 Python2 移植到 Python3。 python3 不存在 urllib2 及其方法移植到 urllib。 因此,您正在大量使用它并希望将来迁移到 Python3,请考虑使用 urllib。 但是 2to3 工具会自动为您完成大部分工作。

        【讨论】:

          【解决方案9】:

          urllib2 提供了一些额外的功能,即 urlopen() 函数可以让您指定标头(通常您过去必须使用 httplib,这要冗长得多。)更重要的是,urllib2 提供了 @ 987654325@ 类,它允许使用更具声明性的方法来执行请求:

          r = Request(url='http://www.mysite.com')
          r.add_header('User-Agent', 'awesome fetcher')
          r.add_data(urllib.urlencode({'foo': 'bar'})
          response = urlopen(r)
          

          注意urlencode()只在urllib中,不在urllib2中。

          还有用于在 urllib2 中实现更高级 URL 支持的处理程序。简短的回答是,除非您使用的是遗留代码,否则您可能希望使用 urllib2 中的 URL 打开器,但您仍然需要将某些实用程序功能导入 urllib。

          奖励答案 使用 Google App Engine,您可以使用 httplib、urllib 或 urllib2 中的任何一个,但它们都只是 Google 的 URL Fetch API 的包装器。也就是说,您仍然受到相同的限制,例如端口、协议和允许的响应长度。不过,您可以使用库的核心来检索 HTTP URL。

          【讨论】:

          • 如何使用 urllib2 创建一个带有编码查询字符串的 url?这是我使用 urllib 的唯一原因,我想确保我以最新/最好的方式做所有事情。
          • 和我上面的例子一样,你使用 urllib2 中的urlopen()Request,你使用 urllib 中的urlencode()。只要确保使用正确的 urlopen,使用这两个库并没有真正的危害。 [urllib docs][1] 清楚地表明使用它是公认的用法。 [1]:docs.python.org/library/urllib2.html#urllib2.urlopen
          • 我用this gist 表示urllib2.urlopen ;也包含其他变体。
          • urllib2 不支持 put 或 delete,这很痛苦
          • requests 也允许自定义标题:docs.python-requests.org/en/master/user/quickstart/…
          【解决方案10】:

          您通常应该使用 urllib2,因为这有时会通过接受 Request 对象使事情变得更容易一些,并且还会在协议错误时引发 URLException。但是,对于 Google App Engine,您也不能使用。您必须使用 Google 在其沙盒 Python 环境中提供的 URL Fetch API

          【讨论】:

          • 你所说的关于 appengine 的说法并不完全正确。您现在实际上可以在 App Engine 中使用 httplib、urllib 和 urllib2(它们是 url fetch 的包装器,这样做是为了让更多代码与 appengine 兼容。)
          • 啊,一定是新的。我的代码上次尝试失败,必须重写才能使用 fetch...
          • urllib2 在 Python 3 中根本不存在
          • @Boris 迁移到urllib.requesturllib.error
          【解决方案11】:

          我喜欢urllib.urlencode 函数,它似乎在urllib2 中不存在。

          >>> urllib.urlencode({'abc':'d f', 'def': '-!2'})
          'abc=d+f&def=-%212'
          

          【讨论】:

          • 请注意,注意 urlencode,因为它不能直接处理 对象——您必须在将它们发送到 urlencode (u'blá'.encode('utf- 8'),或其他)。
          • @user18015:我认为这不适用于 Python 3,你能澄清一下吗?
          • 正如我上面提到的,应该更新这个问题和各种答案,以澄清 Python 3 中的 urllib 是另一种选择,以各种方式清理。但幸运的是,官方文档还指出“Requests 包推荐用于更高级别的 HTTP 客户端接口。21.6. urllib.request — Extensible library for opening URLs — Python 3.6.3 documentation
          • urllib2 在 Python 3 中根本不存在
          • 它在 Python 3 中移至 urllib.parse.urlencode。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-04-10
          • 2013-01-11
          • 2015-11-25
          • 2011-06-13
          • 2023-03-28
          • 1970-01-01
          相关资源
          最近更新 更多