专栏名称: Python开发者
人生苦短,我用 Python。伯乐在线旗下账号「Python开发者」分享 Python 相关的技术文章、工具资源、精选课程、热点资讯等。
目录
相关文章推荐
Python猫  ·  Python 潮流周刊#76:用 50 行 ... ·  3 天前  
Python猫  ·  Python 潮流周刊#76:用 50 行 ... ·  3 天前  
Python中文社区  ·  特朗普成为美国史上首位支持加密货币的总统 ·  5 天前  
Python爱好者社区  ·  大语言模型基础与前沿.pdf ·  4 天前  
Python爱好者社区  ·  yyds!100个即插即用缝合模块(附下载) ·  1 周前  
Python爱好者社区  ·  姜萍造假实锤!阿里数赛出结果。。。 ·  1 周前  
51好读  ›  专栏  ›  Python开发者

逃离 Python 2

Python开发者  · 公众号  · Python  · 2016-11-26 22:01

正文

(点击上方公众号,可快速关注)


译文:伯乐在线 - 飞哥的咖啡

英文:Aaron Meurer

点击 → 了解如何加入专栏作者

如需转载,发送「转载」二字查看说明


大约一个月前,我 tweet 了这条消息:


想一想以下的情景:找到一群大型 Python 库的维护人员,让他们签订并声明 2020 年不再对 Python 2.7 提供支持。


— Aaron Meurer (@asmeurer) 2016/3/22


编辑的话:有一些人已经开始这项工作,它在逐渐变成现实。欲知详情,请参阅 https://python3statement.github.io/


以防你们不知道,我要告诉你们,Python 2.7 将于 2020 年结束生命(原计划在 2015 年结束,但因为迁移至新版本的难度过于巨大,在 2014 年得到延期)。“结束生命”意味着 Python 核心团队不会再对其支持,甚至是安全性更新。


我写下这篇博文是希望声明我为什么赞同这件事,并澄清一些误解,其中最重要的一条误解是,库开发者想要与那些愿意或必须使用 Python 2 的人作对。


我从一名库开发者的角度,写下这篇文章。我是 SymPy 的主要开发者,我对其他的库开发者深表同情。1我这么说是因为我的想法可能会让“用户”有些紧张(尽管我讨厌这种“开发者/用户”的区分)。


Python 2


有很多原因让我认为库应该在 2020 年放弃(并声明将放弃)对 Python 2 的支持(实际上,这个时间点要提早一些,比如说 2018 或 2019 年,这取决于库的重要程度)。


首先,这里的库开发者必须是主要开发者。从开始迁移至 Python 3 到现在来看,这点是显而易见的。看看以下三类人(可能互有交集):CPython 核心开发者,库开发者以及用户。核心开发者必须是迁移至 Python 3 的领头羊,因为他们是代码的编写者。他们也提供了 Python 3 的相关信息,这些信息会随着时间不断变化。我认为,核心开发者应该是更有号召力的。2然后才是库开发者和用户。一个主要的区别在于,用户可能只使用一个版本的 Python。为了让他们从使用的版本转移到 Python 3 上,他们使用的所有库都必须支持它。这个过程需要时间,因为如果没有人使用 Python 3,库开发者就几乎没有动力去支持它(这看上去就像是一个悖论)。更糟糕的是,低于 Python 2.6 的版本中,单一代码库的兼容性简直一团糟。


尽管如今几乎所有的库都支持 Python 3,同时那些不支持的库也想要支持它,


但这一切都要在库开发者迁移至 Python 3 后才会发生。我认为库也需要率先逃离 Python 2,以下是一些重要的原因:


  • Python 2.7 将于 2020 年结束生命。这代表了终止所有的更新,包括安全性更新。事实上到那时,Python 2.7 将成为一个不安全的语言。

  • 要同时支持两个主要版本的 Python,这对与每个项目而言都是技术负担。尽管编写跨版本兼容性代码比以前要容易得多,你仍然得在每个文件的顶部加入 __future__ imports,从你的兼容文件或库中引入所有相关的 buildins,并在 Python 2/3 中运行所有的测试。对于库开发者而言,同时支持两个版本是一个巨大的认知上的负担,因为他们必须了解两种语言的重要区别。针对字符串相关的库开发者,需要知道其在 Python 2/3 的环境下如何运作。一般而言,隐晦的工作区需要进行协调工作(小测试:如何编写 Unicode 字符以同时兼容 Python 2/3?)。

  • 一些 Python 3 的新语法特性(比如 Python 2 中无法使用的那些)只针对库开发者。强制关键字参数 (keyword-only arguments) 就是一个极好的例子。站在 API 的角度,几乎所有的关键字参数实体都应该以强制关键字参数执行。这避免了错误,由于未命名关键字而通过关键字参数的反模式所引起,并且允许将来在不破坏 API 的情况下,对函数的 argspec 进行拓展。


第二个支持库开发者在 2020 年前放弃 Python 2 的原因,则完全是个人因素。我听到的对 tweet 的回复中(包括别处),有一条是这样说的,库应该提供给人们萝卜(吸引人的事物,引申为好处),而非棍子。换言之,与其强迫人们放弃使用 Python 2,不如引诱他们使用 Python 3。这种言论本身具有一些争议。首先,Python 3 已经具备了数不清的好处。平心而论,Python 3 自身对 Unicode 支持得还行就算是一个好处。4


如果你不处理字符串,或者处理却不关心带着奇怪口音的愚蠢外国人的奇葩名字,它还有其他的好处。针对 SymPy,1/2 在Python 2 中的输出为 0,这一点普遍让新用户感到困惑。想象写下 1/2*x + x**(1/2)*y*z – 3*z**2,你会奇怪为什么写下的瞬间内容“消失”了一半(知足吧,这种情况在我们修复打印机前更加严重)。尽管 SymPy 中整数不能得出有理数是一个主要问题,但给出一个浮点数也绝对好过给出一个明显错误的答案。不使用字符串或整数?我这还有其他的好处。


坦诚得说,如果这些好处还没有吸引到你,我敢打赌你一定不是那种能被好处所诱惑的人。


其次,有些好处必须依赖库的运行才能获得。有一些特性只能在同时兼容 Python 2/3 的代码中,或只能在 Python 3 中实现(比如 @矩阵乘法),然而,还有一些特性比如强制关键字参数,只能在不支持 Python 2 的代码中实现。要在 Python 2 中支持它们会是一个技术负担(比如,你可以想象试着支持强制关键字参数,通过人工使用 **kwargs,或利用一些可怕的元编程)。


第三点,就如我所说的,我是自私的。Python 3 确实有一些好处,这正是我想要的。只要我的代码支持 Python 2,我就无法使用强制关键字参数、拓展参数包、Async/Await、以及其他不支持跨版本兼容代码的众多特性。


可能有人要反驳,与其让现有的库阻碍用户,开发者应当创建只支持 Python 3 的新库,并充分利用 Python 3 那些激动人心的新特点。我也同意这样的做法,但是,现有的库也很棒。我不赞同开发者摒弃所有开发完善的库,仅仅是为了使用他们感兴趣的 Python 新功能。


传统 Python


许多人将 Python 2 称为“传统 Python (Legacy Python)”,使用这个短语通常带有几分优越感,但它也令很多人恼火(这篇博文是我第一次使用这个词)。然而,我认为确实如此,Python 2 是一个“传统”系统。如果你想要使用它,不论出于什么原因,都是可以的,但你却无法使用 Python 最新的特性,更无法使用最新版本的库。那些具备许多开发资源的库可能会支持老旧的 Python 2,修复错误和/或安全性问题的兼容版本。但 Python 2 自身的支持也只到 2020 年。而没有资源的库则不会支持(记住,开源的库是不收费的)。


我理解一些人因为某些原因,必须使用 Python 2。但使用过时的软件需要付出代价。迄今,大部分的库都负担着技术负担,但这不是常态。这种负担只会加重,特别是由于你不愿意使用更新的、更好的 Python 3 版本,所带来的技术机会成本的增长。在某个时间点,你必须转移这种负担。那些有财力资源的库可能会将这种负担转移给别处,5比如说,通过将特性或错误修正移植到老旧的支持 Python 2 的库(或通过帮助迁移代码到 Python 3)。


我想要指出,不论出于何种目的,如果你仍然在使用 Python 2,你可能会担心如果库突然只支持 Python 3,并开始使用新特性,是否会破坏你的代码?答案是不会。假设包维护者正确地标记了包上的原数据,类似 pip 和 conda 的工具将不会在 Python 2 上安装非 Python 2 的兼容版本。


如果你还没有迁移至 Python 3,但想要多了解一点,官方文档是一个很好的开始。我同样也强烈推荐你使用 conda 环境,它能轻易地将你的 Python 2 代码从 Python 3 代码中分离出来。


脚注




1、尽管这么说,这完全是我个人的想法,并不代表其他人,也不代表 SymPy 的官方政策(现在论坛还没有做出决定)。


2、感觉 Python 本身并没有真正地想让人使用 Python 3。拿小事来看,文档链接重导至 Python 2 或 PEP 394,这就像在说,Python 应该指的就是 Python 2。


3、Swift 作为苹果针对 iOS 和 OS X 的新语言,函数参数名默认是“关键字限定”的。


4、以此为例,在 conda 中,如果你在根域环境中使用 Python 2,然后安装到非 ASCII 字符的路径中,这是不支持的。这在 Windows 中很常见,因为 Windows 默认使用用户全名作为用户名,而 conda 默认的安装路径为用户目录。


Python 3 则不会发生这种情况,因为为了修复这个问题,conda 中出现字符串的每一个地方在 Python 2 中都必须改为 Unicode 字符串。在 Python 2 中可能会出现类似 ‘π’ + u’i’ 得到 UnicodeDecodeError 这样基本的情况(然而,’π’ + ‘i’, u’π’ + ‘i’ 和 u’π’ + u’i’ 就没有问题)。你可以在这儿了解到对这个问题更详细的描述。顺带一说,这也是我认为你永远不应该在 Python 2 中使用 from __future__ import unicode_literals 的理由。


我已经不再用 conda 了,但是据我所知,这个问题仍未解决。当然,如果 conda 在 Python 3 中运行,它能正常工作。


5、如果你对此感兴趣,我听说 Continuum 也许能帮助到你。


关注「Python开发者」

看更多精选Python技术文章

↓↓↓