Python 2 還能走多遠?
作者丨cunshun
導語 自2020年Python 2停止維護至今,5年過去了。雖然還有很多項目依舊在使用Python 2,但不可否認,無論是企業還是社區,都在努力向Python 3邁進。Python 2簡潔易讀、靈活易上手、支持庫豐富,但隨著大規模使用,亦逐漸暴露出各種不足。尤其是近些年Python維護者們通過持續補丁對Python 2進行優化和修復,但其底層架構和實現上的問題依然無法完全解決。為什么要升級到Python 3?如何在TencentOS Server 4中進行升級?

最近在做TS4的升級工作,遇到比較多的問題是:
- Python2不能用了嗎?
- Python3有啥好處,為啥要升?
- 有沒有什么方法一鍵升級到Python3?
這里在開頭先簡單統一回答一下:
- Python2停止維護后積累很多的安全漏洞、bug,官方也不再修復,存在嚴重的使用風險,不建議繼續使用。
- 升級 Python3 可以獲得更全更新的模塊支持、更強的性能、更好的編程語法、更長的維護保障等等。
- 沒有一鍵升級的辦法,簡單的python代碼或許可以,復雜一點的項目需要搭配多種手段來適配。
接下來我們針對上面的問題,具體展開。
一、Python 2 的前世
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. 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". Python's exception model also resembled Modula-3's, with the addition of an else clause. In 1994 comp.lang.python, the primary discussion forum for Python, was formed.
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".
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.
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
二、Python 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。
PSF官網也發布Python2停止維護的公告:https://www.python.org/doc/sunset-python-2/
2. 大勢所趨?
雖然社區呼吁大家切換到Python3,那實際情況是什么樣子呢?Python官方給出了一些項目的Python使用時間線。


在Python公布出來的一些項目名單中,可以看到很多項目(sphinx, pillow,pandas,numpy,apache spark等),在20年后的新版本,就不再支持python2,而僅支持Python3了(綠色表示兼容python2,藍色表示只支持python3)。包括后續新增的項目,都會優先基于python3來構建。

提示:更多項目宣布后續會不再支持python2: https://python3statement.github.io/
三、Python 2不能用了嗎?
Python2已經挺好了,為什么還要造一個差別這么大的Python3?我的項目在Python2上跑的好好的,為什么要費勁巴拉地適配Python3?
估計大多數人都會有上面這些疑問,Python維護者們也知道要讓開發者從2切到3,就必須解釋這些問題,如果有時間,大家可以去看看Python維護者們針對 Python3 存在的一些文章和郵件,里面有很多細節。這里主要列出幾個普通開發者遇到最多的問題:
3. Python 2 的文本和二進制處理混亂
Python2中的 str 同時承擔了 “文本”和“字節”兩種語義,才導致了 Python 3 的改進:明確區分文本(str)和字節(bytes)。例如下面這個字符串,在Python3里,他只是表示由“a”、“b”、“c”和“d”組成的字符串。
'abcd'但是在Python2里他卻可能是代表 97、98、99 和 100 的字節,所以在Python2里,你既可以把他當字節用也可以把他當字符串用,很容易出錯。但是在Python3中,做了嚴格的區分,這樣就可以保證代碼中使用不會出現問題。
操作 | Python2行為 | Python3行為 |
| 合法,結果是'abcd' + 'efg' | 合法,結果是'abcd' + 'efg' |
| 合法,結果是'abcd' + 'efg' | 報錯,類型不兼容 |
| 等價于'abcd' | bytes類型 |
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)) # <type 'str'>
print(s) # 可能亂碼,或者報錯
# 正確做法
u = u'你好' # Unicode字符串
print(type(u)) # <type 'unicode'>
print(u) # 正常顯示下面是一個demo,展示了Python2里面如何對字符串進行編解碼。
# 假設 s = '中文',文件頭聲明了 utf-8
s = '中文' # s 是 str 類型,utf-8 編碼的字節串
u = s.decode('utf-8') # u 是 unicode 類型
print(type(u)) # <type 'unicode'>
# 反過來
s2 = u.encode('utf-8') # s2 是 str 類型
print(type(s2)) # <type 'str'>參考:https://snarky.ca/why-python-3-exists/
四、Python 3有啥好處?
1. Python 3的優化
Python3,在性能方面做了很多改進,下面列出了其中一些。
(1) 對象的 __dict__ 共享鍵存儲(PEP 412, Python 3.3)
- 多個同類型對象的 __dict__(屬性字典)可以共享鍵的存儲空間。
- 優點:當你創建大量自定義對象時,節省內存并提升訪問速度。
(2) OrderedDict 用 C 實現(Python 3.5)
- collections.OrderedDict 由純 Python 實現變為 C 實現。
- 優點:性能提升 4 到 100 倍,插入和遍歷更快。
(3) GIL(全局解釋器鎖)行為更可預測(Python 3.2)
- 舊版 GIL 按 Python 字節碼數讓出控制權,耗時不穩定。
- 新版 GIL 按時間片(默認5ms)讓出控制權,線程調度更公平、可預測。
(4) io 庫用 C 重寫(Python 3.1)
- Python 2.7 的 io 庫是純 Python 實現,Python 3.1 起用 C 實現。
- 優點:文件和流的讀寫操作更快。
參考:https://eev.ee/blog/2016/07/31/python-faq-why-should-i-use-python-3/
2. 業內的應用實例
同時,業內已經有不少企業通過 Python2 切換到 Python3 獲得了性能和資源利用上的提升。例如 Instagram,通過適配Python3,獲得了 12% CPU 性能提升以及 30% 的內存節省效果。

數據來源:https://www.youtube.com/watch?v=66XoCk79kjM&t=2346s
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. 更多、更好的模塊支持

除了上面提到一些老組件后續不會支持python2,只支持python3之外。因為近兩年AI勢頭興起,AI相關的組件Python占大頭,這些Python組件大部分也只支持Python3。
(1) 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(2) 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"]五、如何切換到Python 3
1. python 2項目適配到python 3的方法(推薦)
(1) python2移植python3指南:https://portingguide.readthedocs.io/en/latest/index.html
(2) python2兼容python3工具:
- https://github.com/PyCQA/modernize
- https://github.com/benjaminp/six
(3) python2->python3轉化工具:https://docs.python.org/3.12/library/2to3.html
上面提到的 modernize 工具,一樣也有從將代碼從python2自動轉化為python3的功能,只是后者會偏向于做一些能夠兼容python2的修改。
(4) 格式和錯誤檢查:https://github.com/astral-sh/ruff
(5) 類型檢查:https://github.com/microsoft/pyright
(6) 測試套:
- 因為工具轉化不是100%覆蓋,所以可能還需要一定的測試用例保證功能正常
- 可以用pytest等測試用例來進一步保證代碼正常
遷移思路:
- 如果決心遷移到Python3,可以好好看一遍Python2->Python3的指南,然后再通過2to3/modernize轉換,轉換之后通過ruff/pyright工具進行二次確認檢查,最后運行自己的測試代碼保證功能正常。
- 如果還是想先用Python2過渡,可以通過python-six工具兼容一些Python2和Python3之間的不兼容庫接口。
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項目,來從根本上解決這些問題。
正是因為軟件飛速發展,老版本系統存在一些從根本上無法解決的問題,可能是軟件本身,也可能是一些政治經濟上的原因,所以才會有版本升級的存在。業務一旦跑起來就不想升級很正常,但是在技術更迭的大潮流下,不斷更新接納新的事物也是業務能持續發展的立身之本,畢竟誰都不想做那個被拍在沙灘上的人是吧。






















