Python 3 对其标准库中的许多模块进行了重命名、重组、功能增强和现代化改造,以使其命名更清晰、功能更强大,并更好地适应 Python 3 的设计理念(如更严格的 Unicode 支持)。

以下是几个最关键、最常见的模块差异点:
print 语句 vs print() 函数
这是最著名、也是影响最广的变化。
-
Python 2:
print是一个语句。# Python 2 print "Hello, World!" # 直接打印 print "Hello", "World" # 打印两个值,并用空格分隔 print >> sys.stderr, "Error!" # 打印到标准错误流
-
Python 3:
print是一个内置函数。
(图片来源网络,侵删)# Python 3 print("Hello, World!") # 作为函数调用,必须有括号 print("Hello", "World") # 函数参数,默认用空格分隔 print("Hello", "World", sep="|") # 可以指定分隔符 print("Hello", "World", end="\n") # 可以指定结尾符 # print >> sys.stderr, "Error!" # 这种语法已不再支持 import sys print("Error!", file=sys.stderr) # 使用 file 参数指定输出流
迁移影响: 所有使用 print 的代码都需要修改,可以使用 2to3 工具自动完成大部分修改。
核心库模块的重命名与合并
Python 3 将一些功能相似或重复的模块进行了合并,并统一了命名风格(通常是 foo 或 foo_py 风格)。
| Python 2 模块 | Python 3 模块 | 说明 |
|---|---|---|
ConfigParser |
configparser |
统一为小写。 |
Queue |
queue |
统一为小写。PriorityQueue 等也在此模块中。 |
SocketServer |
socketserver |
统一为小写。 |
repr |
repr |
内置函数,模块名未变,但功能行为有细微差别(见下文)。 |
commands |
已移除 | 功能被 subprocess 模块完全取代。这是最重要的迁移点之一。 |
__builtin__ |
builtins |
内置函数和异常所在的模块名改变。import __builtin__ -> import builtins。 |
urllib2, urlparse, robotparser |
urllib, urllib.parse, urllib.robotparser |
在 Python 3 中被重组到 urllib 包下。 |
BaseHTTPServer, SimpleHTTPServer |
http.server |
合并到 http.server 模块。 |
SocketSSL |
ssl |
功能整合到 ssl 模块。 |
cPickle |
pickle |
cPickle 模块被移除。pickle 模块现在默认使用 C 语言实现,性能和 cPickle 一样好。 |
迁移影响:
- 直接导入错误: 如果你直接导入
import ConfigParser,在 Python 3 中会直接报错,需要修改为import configparser。 - 功能迁移: 对于
commands模块,需要将commands.getstatusoutput()等调用重写为使用subprocess模块的等效代码。
unicode 与 str 的根本性变化
这是理解 Python 2 和 Python 3 模块行为差异的基础。
-
Python 2:
str: 字节串。'hello'是一个字节串。unicode: Unicode 字符串。u'hello'是一个 Unicode 字符串。- 混合使用
str和unicode经常会导致UnicodeDecodeError或UnicodeEncodeError,处理文件 I/O、网络请求时,需要手动进行编解码。
-
Python 3:
str: Unicode 字符串,这是文本的默认类型。'hello'是一个 Unicode 字符串。bytes: 字节串,这是二进制数据的类型。b'hello'是一个字节串。- 这种设计使得文本和二进制数据分离得非常清晰,减少了编码错误。
模块层面的影响: 所有处理 I/O、网络、文件、数据的模块都必须适应这个变化。
-
文件操作:
- Python 2:
open('file.txt', 'r')默认以系统编码读取文件,可能出错,推荐使用io.open()并指定编码。 - Python 3:
open('file.txt', 'r')默认以文本模式打开,返回str对象。open('file.txt', 'rb')以二进制模式打开,返回bytes对象,编码问题被更好地封装。
- Python 2:
-
json模块:json.loads()接受一个str(包含 JSON 文本) 并返回一个 Python 对象。json.dumps()接受一个 Python 对象并返回一个str。- 如果你有一个
bytes对象,需要先解码成str:json.loads(my_bytes.decode('utf-8'))。
-
re(正则表达式) 模块:- Python 2:
re模块函数可以接受str或unicode字符串,如果模式是str而字符串是unicode,它会尝试隐式解码,这可能导致不可预测的行为。 - Python 3:
re模块被严格化,模式字符串和被处理的字符串必须是同一种类型,要么都是str,要么都是bytes,这迫使开发者更清晰地思考是在处理文本还是二进制数据。
- Python 2:
第三方库的兼容性
这是实际开发中遇到最多的问题。
-
现状:
- 仅支持 Python 2: 许多老旧项目或特定工具库(如一些科学计算库的旧版本)已停止更新,不再维护。
- 仅支持 Python 3: 大多数现代库和框架(如 Django, Flask, Pandas, NumPy, Requests 等)都已转向 Python 3。
- 支持 Python 2 和 Python 3 (兼容层): 许多库通过
six、future、past等工具来同时支持两个版本。
-
如何处理:
- 首选方案: 尽可能使用只支持 Python 3 的库,这是未来的趋势。
- 遗留系统: 如果必须使用一个只支持 Python 2 的库,那么你的项目暂时无法迁移到 Python 3,你需要考虑:
- 是否有替代的、支持 Python 3 的库?
- 是否可以自己动手修改或 Fork 这个库(如果许可证允许)?
- 在容器或虚拟环境中保留一个 Python 2 的运行环境来运行这个特定库(不推荐,会增加系统复杂性)。
迁移策略与工具
面对这些模块差异,如何有效地进行迁移?
-
使用自动化工具:
2to3: Python 自带的翻译工具,它可以自动修复大部分语法和模块导入问题(如print语句、ConfigParser等),你可以对单个文件或整个项目运行它。modernize: 一个更智能的第三方工具,它基于lib2to3,但会建议使用更现代的 Python 3 风格的代码,而不仅仅是修复语法错误。
-
使用兼容性库:
-
six: 一个轻量级的库,用于编写在 Python 2 和 Python 3 上都能运行的代码,它提供了一些辅助函数和类来弥合两个版本之间的差异。# 使用 six 来兼容 print from six import print_ print_("Hello, World!") # 使用 six 来兼容字符串类型 import six text_type = six.text_type # 在 Python 2 中是 unicode, Python 3 中是 str binary_type = six.binary_type # 在 Python 2 中是 str, Python 3 中是 bytes -
future: 一个更全面的库,它允许你在 Python 2 代码中导入 Python 3 的行为(from __future__ import print_function)。
-
-
使用条件导入: 对于一些简单的模块名变化,可以使用
try...except来处理。try: # 尝试 Python 3 的导入方式 import configparser except ImportError: # 如果失败,说明是 Python 2,使用旧的名字 import ConfigParser as configparser这种方法对于少量模块有效,但如果差异很大,代码会变得很臃肿。
| 方面 | Python 2 | Python 3 | 迁移要点 |
|---|---|---|---|
print |
语句 | 函数 | 所有 print 语句需加括号。 |
| 模块命名 | 混合风格(如 ConfigParser) |
统一小写风格(如 configparser) |
导入语句需修改。 |
| 模块合并 | 功能分散(如 urllib2) |
功能重组(如 urllib.request) |
导入路径和API可能改变。 |
| 字符串 | str (字节), unicode (文本) |
str (文本), bytes (字节) |
文本和二进制数据分离,I/O处理方式改变。 |
| 第三方库 | 大量库仅支持 Python 2 | 主流库已转向 Python 3 | 评估依赖库的兼容性是迁移的关键。 |
迁移过程本质上就是系统性地识别并修复所有因这些核心差异而导致的代码不兼容问题,从自动化工具开始,然后针对遗留问题手动修复,是最高效的迁移路径。
