Requests vs. urllib:它解决了什么问题?
对于 Python 新手来说,Python 较令人费解的方面之一就是,当涉及到编写 HTTP(S) 协议客户端时,标准库的 urllib
模块和流行的(及备受推崇的)第三方模块 requests
之间鲜明的可用性差异。当你的问题是“与 HTTP 服务器进行通信”时,可用性方面的差异并不是那么明显,但一涉及到额外的需求,像 SSL/TLS、鉴权、重定向处理、会话管理和 JSON 请求/响应主题,差异就明显起来。
想要 记录易用性的差异 是诱人而完全可以理解的,直到 requests
是"Pythonic" (在 2016 年), 而 urllib
现在已经不 Pythonic 了 (尽管被包含在了标准库中)。
虽然当然有那么点因素(例如,内置的 property
是在 Python 2.2 才添加进来的,而 urllib2
被包含在原始的 Python 2.0 发布中,因此在其 API 设计中无法考虑这点),但是绝大多数的可用性差异涉及到了我们经常忘记问问所使用的软件的一个完全不同的问题:它解决了什么问题?
即, urllib
/ urllib2
和 requests
之间的许多令人惊讶的其他差异可以由它们解决不同的问题这一事实,以及较之于 Jeremy Hylton 在十年前想要解决的问题,现今大多数 HTTP 客户端开发者所遇到的问题更接近于 Kenneth Reitz 在 2010/2011 年设计 requests
用以解决的问题来解释。
答案都在名字里了
引用当前的 Python 3 urllib
包文档:“urllib 是一个收集几个处理 URL 模块的包”。
以及来自 Jeremy 的添加 urllib2
到 CPython 的 原始提交信息 的文档字符串:“使用各种协议,用于打开 URL 的可扩展库”。
等等,神马?我们只是想写一个 HTTP 客户端,所以为什么文档谈到一般的 URL 相关工作?
虽然,对于那些习惯于现代的 HTTPS+JSON 驱动的交互式 web 的开发者来说有点奇怪,但是事情为什么会变成这样并不总是清晰的。
在世纪之交,所期望的是,保留丰富多样的数据传输协议,并且为不同的目的进行不同的特点优化,而标准库中最为有用的客户端则是那个可以用来与多种不同类型的服务器(例如 HTTP, FTP, NFS 等等)进行通信,客户端开发者无需过多担心使用的特定的协议(由 URL schema 所示)。
然而,在实践中,事情并非如此(大多数是因为严格的防火墙制度,这意味着 HTTP 服务器是唯一一个可被可靠访问的远程服务),所以,在 2016 年,人们现在经常拿专用的仅 HTTP(S) 客户端库的可用性和在获取大多数 HTTP(S) 特性之前需要专门配置使用 HTTP(S) 的通用的 URL 处理库进行比较。
在编写它的时候, urllib2
是被设计来适合“通用 URL 处理”这一方孔的方钉。相比之下,大多数的现代客户端开发者在寻找适合“HTTPS+JSON 处理”这一圆孔的圆钉 —— 如果你先把角磨圆,那么 urllib
/ urllib2
就会适用,但 requests
则已经是圆的了。
所以,为什么不把 requests 添加到标准库中呢?
对"它解决了什么问题?"这个不那么明显的问题的回答,会到一个明显得多的后续问题:如果 urllib
/ urllib2
被设计来解决的问题不再常见,而 requests
解决的问题是常见的,那么为什么不把 requests
添加到标准库中呢?
如果我记得没错,在 2013 年左右(在 requests
1.0 发布后) 的一次语言提交中,Guido 在原则上认可了这个想法,而在核心开发者团队中,无论是 requests
本身(可能作为一个独立升级组件的捆绑快照),还是带有不一样实现的的 API 兼容子集,最终都会出现在标准库中,这是一个相当常见的假设。
然而,即使撇开 requests 开发者关于此想法的疑惑 ,让 requests
作为标准库组件的一部分,仍然有一些不一般的系统集成问题要解决。
特别是,其中之一是,requests 确实更可靠地以跨平台的方式处理 SSL/TLS 证书是捆绑包含在 certifi
项目中的 Mozilla 证书捆绑(Mozilla Certificate Bundle)。这是默认情况下(由于以跨平台的方式获得对系统的安全证书的可靠访问的困难)的一个明智之举,但它与标准库的安全策略(具体是将证书管理委托给底层操作系统)相冲突。这项策略的目的是解决两个需求:允许 Python 应用程序访问添加到系统证书存储的自定义机构证书(最值得注意的是,适用于大型组织的私有 CA 证书),并避免增加当根证书捆绑出于任何其他原因而改变时,需要更新的额外的证书存储到终端用户系统。
这类问题在技术上是可以解决的,但解决它们并不好玩,并且帮助解决它们的人手头上已经有许许多多其他的要求。这意味着,只要大部分的 CPython 和 requests
开发者将其贡献作为业余时间的活动,而不是专门被雇佣来做的事,那么在这个方面我们可能不会看到太多进展。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: Python 中 Meta 类习语的起源
下一篇: RPython 的魔力
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论