作者:cunshun
丨 导语 自2020年Python 2停止维护至今,5年过去了。虽然还有很多项目依旧在使用Python 2,但不可否认,无论是企业还是社区,都在努力向Python 3迈进。Python 2简洁易读、灵活易上手、支持库丰富,但随着大规模使用,亦逐渐暴露出各种不足。尤其是近些年Python维护者们通过持续补丁对Python 2进行优化和修复,但其底层架构和实现上的问题依然无法完全解决。为什么要升级到Python 3?如何在TencentOS Server 4中进行升级?
最近在做TS4的升级工作,遇到比较多的问题是:
1.Python2不能用了吗?
2.Python3有啥好处,为啥要升?
3.有没有什么方法一键升级到Python3?
这里在开头先简单统一回答一下:
1.Python2停止维护后积累很多的安全漏洞、bug,官方也不再修复,存在严重的使用风险,不建议继续使用。
2.升级 Python3 可以获得更全更新的模块支持、更强的性能、更好的编程语法、更长的维护保障等等。
3.没有一键升级的办法,简单的python代码或许可以,复杂一点的项目需要搭配多种手段来适配。
接下来我们针对上面的问题,具体展开。
1.1 Python 2的发布
在 Python 2 之前,还有一个在 1991 年 2 月 发布的 Python 0 和 在1994 年 1 月发布的 Python 1。
一些核心功能在Python0 上已经具备,例如异常处理、函数的类以及各种核心数据类型,如 list
、dict
和 str
等等。
Van Rossum first published the code (for Python version 0.9.1) to alt.sources in February 1991.[12][13] Several features of the language were already present at this stage, among them classes with inheritance, exception handling, functions, and various core datatypes such as list
, dict
, and str
. The initial release also contained a module system borrowed from Modula-3; Van Rossum describes the module as "one of Python's major programming units".[1] Python's exception model also resembled Modula-3's, with the addition of an else
clause.[3] In 1994 comp.lang.python, the primary discussion forum for Python, was formed.
[1]
Python1,又加入了一些函数式编程工具 lambda
、map
、filter
和 reduce
的功能。
Python reached version 1.0 in January 1994. The major new features included in this release were the functional programming tools lambda
, map
, filter
and reduce
. Van Rossum stated that "Python acquired lambda, reduce(), filter() and map(), courtesy of a Lisp hacker who missed them and submitted working patches".[14]
Python2,在2000年10月发布,从此一个持续了20年的版本帝国拉起帷幕。
Python 2.0, released October 2000,[8] introduced list comprehensions, a feature borrowed from the functional programming languages SETL and Haskell. Python's syntax for this construct is very similar to Haskell's, apart from Haskell's preference for punctuation characters and Python's preference for alphabetic keywords. Python 2.0 also introduced a garbage collector able to collect reference cycles.[8]
1.2 Python 2的演进
下面这个表展示了整个Python的版本发布历程,看到每个版本发布的间隔和到终止维护基本上在5年内,但是只有最后一个2.7版本,在2010年发布,又继续维护了10年之久,甚至很多人都觉得Python2会一直维护下去。
看下面这张图时间线更清楚一点。python2.7很长一段时间内和python3共存,所以这段时期在各大主流发行版中,都会同时提供 Python2 和 Python3 两个Python版本。
来源:https://zh.wikipedia.org/wiki/Python%E7%9A%84%E6%AD%B7%E5%8F%B2
2.1 Python 2 的最后一舞
Python2官方一开始宣布在2020年1月1日停止维护。https://pythonclock.org/
但是后来PSF将Python2的实际停用时间更新为2020年4月。
https://www.python.org/psf/press-release/pr20191220/
这一举措引起了一些Python使用者的不满,甚至发起了请愿,要求取消2.7.18版本的发布。
https://discuss.python.org/t/petition-abandon-plans-to-ship-a-2-7-18-in-april/2946
后来官方解释的说法是2.7.18的代码仓在2020.1.1已经被冻结,但是版本发布在4月:)。
不管怎样,这个巨无霸版本最终还是在2020年落下帷幕,2.7.18,作为Python2的最后一个版本,在2020年4月发布,同月,Python2.7的维护者在2020年4月发布一封邮件,正式和Python2道别,并呼吁开发者从Python2迁移到Python3.《Python 2.7.18, the end of an era》
PSF官网也发布Python2停止维护的公告:https://www.python.org/doc/sunset-python-2/
2.2 大势所趋?
虽然社区呼吁大家切换到Python3,那实际情况是什么样子呢?Python官方给出了一些项目的Python使用时间线。
在Python公布出来的一些项目名单中,可以看到很多项目(sphinx, pillow,pandas,numpy,apache spark等),在20年后的新版本,就不再支持python2,而仅支持Python3了(绿色表示兼容python2,蓝色表示只支持python3)。包括后续新增的项目,都会优先基于python3来构建。
提示:更多项目宣布后续会不再支持python2: https://python3statement.github.io/
Python2已经挺好了,为什么还要造一个差别这么大的Python3?我的项目在Python2上跑的好好的,为什么要费劲巴拉地适配Python3?
估计大多数人都会有上面这些疑问,Python维护者们也知道要让开发者从2切到3,就必须解释这些问题,如果有时间,大家可以去看看Python维护者们针对 Python3 存在的一些文章和邮件,里面有很多细节。这里主要列出几个普通开发者遇到最多的问题:
3.1 Python 2 的文本和二进制处理混乱
Python2中的 str 同时承担了 “文本”和“字节”两种语义,才导致了 Python 3 的改进:明确区分文本(str)和字节(bytes)。
例如下面这个字符串,在Python3里,他只是表示由“a”、“b”、“c”和“d”组成的字符串。
但是在Python2里他却可能是代表 97、98、99 和 100 的字节,所以在Python2里,你既可以把他当字节用也可以把他当字符串用,很容易出错。但是在Python3中,做了严格的区分,这样就可以保证代码中使用不会出现问题。
| | |
---|
'abcd' + 'efg' | | |
'abcd' + b'efg' | | |
b'abcd' | | |
3.2 Python 2 对Unicode支持不足
从上面的python版本生命线可以看到,python在1991年2月第一次发布,早于 1991 年 10 月发布的 Unicode 标准第一卷。
所以Python2开始只支持ASCII,后续才加入了对Unicode的支持。这就导致在Python2里面处理Unicode比较麻烦,你要处理中文、日文等非 ASCII 字符,必须用 unicode
类型,并且要手动编码/解码,一不留神就会出错。
# Python 2
s = '你好' # 这是utf-8编码的字节串,不是Unicode字符串
print(type(s)) #
print(s) # 可能乱码,或者报错
# 正确做法
u = u'你好' # Unicode字符串
print(type(u)) #
print(u) # 正常显示
下面是一个demo,展示了Python2里面如何对字符串进行编解码。
# 假设 s = '中文',文件头声明了 utf-8
s = '中文' # s 是 str 类型,utf-8 编码的字节串
u = s.decode('utf-8') # u 是 unicode 类型
print(type(u)) #
# 反过来
s2 = u.encode('utf-8') # s2 是 str 类型
print(type(s2)) #
参考:https://snarky.ca/why-python-3-exists/
4.1 Python 3的优化
Python3,在性能方面做了很多改进,下面列出了其中一些。
对象的 __dict__
共享键存储(PEP 412, Python 3.3)
OrderedDict
用 C 实现(Python 3.5)
GIL(全局解释器锁)行为更可预测(Python 3.2)
io
库用 C 重写(Python 3.1)
参考:https://eev.ee/blog/2016/07/31/python-faq-why-should-i-use-python-3/
4.2 业内的应用实例
同时,业内已经有不少企业通过 Python2 切换到 Python3 获得了性能和资源利用上的提升。例如 Instagram,通过适配Python3,获得了 12% CPU 性能提升以及 30% 的内存节省效果。
数据来源:https://www.youtube.com/watch?v=66XoCk79kjM&t=2346s
4.3 benchmark实测
Python 官方在版本发布时,会对 Python 版本进行性能测试:
Python 3.11 的速度比 Python 3.10 快 10-60%。在平均状况下,在标准基准测试(standard benchmark suite)中可见1.25倍的加速效果。
https://docs.python.org/zh-cn/3.11/whatsnew/3.11.html#summary-release-highlights
虽然实际到业务环境中的性能提升可能没有 benchmark 提升那么大(受代码影响),但是在数据上一定是Python3的性能表现更好。
我们也基于一些Python常用软件跑了benchmark测试套,结果显示单纯基础性能 Python3 也比 Python2 要强很多。
TS4(TencentOS Server 4) 搭载了新版本 Python3,而 TS2(TencentOS Server 2) 则还是使用 Python2
4.4 更多、更好的模块支持
除了上面提到一些老组件后续不会支持python2,只支持python3之外。因为近两年AI势头兴起,AI相关的组件Python占大头,这些Python组件大部分也只支持Python3。
Pytorch
例如Pytorch,可以看到Pytorch不仅标注了需要Python3.9以上版本,并且也在删除了原来的python2兼容代码:
https://github.com/pytorch/pytorch?tab=readme-ov-file#prerequisites
# pytorch
If you are installing from source, you will need:
- Python 3.9 or later
vllm
包括vllm也只支持Python3。https://github.com/vllm-project/vllm/blob/main/pyproject.toml
[project]
name = "vllm"
...
classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
...
]
requires-python = ">=3.9,<3.13"
dynamic = [ "version", "dependencies", "optional-dependencies"]
5.1 python 2项目适配到python 3的方法(推荐)
迁移思路:
如果决心迁移到Python3,可以好好看一遍Python2->Python3的指南,然后再通过2to3/modernize转换,转换之后通过ruff/pyright工具进行二次确认检查,最后运行自己的测试代码保证功能正常。
如果还是想先用Python2过渡,可以通过python-six工具兼容一些Python2和Python3之间的不兼容库接口。
5.2 TS 4上安装运行Python迁移工具
TencentOS Server 4下运行含有python2语法的代码会报错,下面的链接中的教程可以将python2的代码转化为python3
https://docs.python.org/zh-cn/3.7/library/2to3.html
其中2to3这个命令在TencentOS Server 4中由 python3-devel 提供,要使用该命令需要安装此包。
dnf install python3-devel -y
来自本文作者的话
其实新旧版本更替,是所有软件的必经之路。我们在开发TencentOS Server 4发行版时,也经历了类似的历程
从2000年到2020年这20年间,正是互联网爆发式发展的时期。数以万计的项目看中了Python简洁易读、灵活易上手、支持库丰富的特点,选择基于Python构建开发。许多大公司也积累了大量的Python代码。作为这个时代的产物,Python 2被广泛使用,甚至伴随了许多Python开发者的职业生涯。
随着大规模的应用,Python维护者意识到了 Python2 本身的一些不足,虽然在近20年的时间里一直通过补丁的方式来对Python2的进行优化修补,但是底层架构和实现上的问题难以彻底解决的。所以Python维护者们依然决定开启新的Python项目,来从根本上解决这些问题。
正是因为软件飞速发展,老版本系统存在一些从根本上无法解决的问题,可能是软件本身,也可能是一些政治经济上的原因,所以才会有版本升级的存在。业务一旦跑起来就不想升级很正常,但是在技术更迭的大潮流下,不断更新接纳新的事物也是业务能持续发展的立身之本,毕竟谁都不想做那个被拍在沙滩上的人是吧。
其他参考:http://python3porting.com/toc.htm