Python 3.0 的新特性 — Python 文档

来自菜鸟教程
Python/docs/3.8/whatsnew/3.0
跳转至:导航、​搜索

Python 3.0 中的新功能

作者
吉多·范罗苏姆

本文解释了 Python 3.0 中与 2.6 相比的新特性。 Python 3.0,也称为“Python 3000”或“Py3K”,是有史以来第一个 故意向后不兼容 Python 版本。 与典型版本相比,有更多的更改,并且对所有 Python 用户来说更重要的更改。 尽管如此,在消化了这些变化之后,您会发现 Python 确实没有发生太大的变化——总的来说,我们主要是修复众所周知的烦恼和缺陷,并删除了很多旧的问题。

本文并不试图提供所有新功能的完整规范,而是试图提供一个方便的概述。 有关完整的详细信息,您应该参考 Python 3.0 的文档和/或文本中引用的许多 PEP。 如果您想了解特定功能的完整实现和设计原理,PEP 通常比常规文档包含更多详细信息; 但请注意,一旦功能完全实现,PEP 通常不会保持最新。

由于时间限制,本文档没有应有的完整。 与新版本一样,源代码分发中的 Misc/NEWS 文件包含有关更改的每个小事情的大量详细信息。

常见的绊脚石

如果您习惯了 Python 2.5,本节列出了最有可能让您感到困惑的少数更改。

视图和迭代器而不是列表

一些著名的 API 不再返回列表:

  • dict 方法 dict.keys(), dict.items()dict.values() 返回“视图”而不是列表. 例如,这不再有效:k = d.keys(); k.sort()。 使用 k = sorted(d) 代替(这也适用于 Python 2.5 并且同样有效)。

  • 此外,不再支持 dict.iterkeys()dict.iteritems()dict.itervalues() 方法。

  • map()filter() 返回迭代器。 如果你真的需要一个列表并且输入序列的长度都相等,一个快速的解决方法是将 map() 包裹在 list() 中,例如 list(map(...)),但更好的解决方法通常是使用列表推导式(尤其是当原始代码使用 lambda 时),或者重写代码使其根本不需要列表。 特别棘手的是 map() 为函数的副作用而调用; 正确的转换是使用常规的 for 循环(因为创建列表只会浪费)。

    如果输入序列的长度不相等,map() 将在最短序列的终止处停止。 为了与 Python 2.x 中的 map() 完全兼容,还将序列包装在 itertools.zip_longest() 中,例如 map(func, *sequences) 变为 list(map(func, itertools.zip_longest(*sequences)))

  • range() 现在的行为类似于 xrange() 以前的行为,除了它适用于任意大小的值。 后者已不复存在。

  • zip() 现在返回一个迭代器。


订购比较

Python 3.0 简化了排序比较的规则:

  • 当操作数没有有意义的自然排序时,排序比较运算符(<<=>=>)会引发 TypeError 异常。 因此,像 1 < 0 > Nonelen <= len 这样的表达式不再有效,例如 None < None 引发 TypeError 而不是返回 False。 一个推论是对异构列表进行排序不再有意义——所有元素必须相互比较。 请注意,这不适用于 ==!= 运算符:不同不可比较类型的对象总是相互不相等。
  • builtin.sorted()list.sort() 不再接受提供比较函数的 cmp 参数。 请改用 key 参数。 NB keyreverse 参数现在是“仅关键字”。
  • cmp() 函数应该被视为消失了,并且不再支持 __cmp__() 特殊方法。 使用__lt__()进行排序,__eq__()__hash__(),以及其他需要的丰富比较。 (如果您确实需要 cmp() 功能,您可以使用表达式 (a > b) - (a < b) 作为 cmp(a, b) 的等价物。)


整数

  • PEP 237:本质上,long 重命名为 int。 也就是说,只有一种内置整数类型,名为 int; 但它的行为主要类似于旧的 long 类型。
  • PEP 238:像 1/2 这样的表达式返回一个浮点数。 使用 1//2 获得截断行为。 (后一种语法已经存在多年,至少从 Python 2.2 开始是这样。)
  • sys.maxint 常量被删除,因为不再有整数值的限制。 但是,sys.maxsize 可以用作比任何实际列表或字符串索引都大的整数。 它符合实现的“自然”整数大小,并且通常与同一平台上以前版本中的 sys.maxint 相同(假设相同的构建选项)。
  • 长整数的 repr() 不再包含尾随的 L,因此无条件去除该字符的代码将截断最后一位数字。 (使用 str() 代替。)
  • 八进制文字不再是 0720 的形式; 改用 0o720


文字对比 数据而不是 Unicode Vs。 8 位

你认为你知道的关于二进制数据和 Unicode 的一切都发生了变化。

  • Python 3.0 使用 text 和(二进制)data 的概念,而不是 Unicode 字符串和 8 位字符串。 所有文本都是Unicode; 然而 encoded Unicode 表示为二进制数据。 用来保存文本的类型是str,用来保存数据的类型是bytes。 与 2.x 情况的最大区别在于,任何在 Python 3.0 中混合文本和数据的尝试都会引发 TypeError,而如果您要在 Python 2.x 中混合使用 Unicode 和 8 位字符串,则会出现如果 8 位字符串碰巧只包含 7 位 (ASCII) 字节,则可以工作,但如果它包含非 ASCII 值,则会得到 UnicodeDecodeError。 多年来,这种特定于价值的行为引起了无数悲伤的面孔。
  • 由于这种理念上的变化,几乎所有使用 Unicode、编码或二进制数据的代码很可能都必须更改。 这种变化是为了更好的,因为在 2.x 世界中有许多错误与混合编码和未编码的文本有关。 要在 Python 2.x 中做好准备,开始对所有未编码文本使用 unicode,仅对二进制或编码数据使用 str。 然后 2to3 工具将为您完成大部分工作。
  • 您不能再将 u"..." 文字用于 Unicode 文本。 但是,您必须对二进制数据使用 b"..." 文字。
  • 由于 strbytes 类型不能混合使用,您必须始终在它们之间进行显式转换。 使用 str.encode()strbytes,使用 bytes.decode()bytesstr。 您也可以分别使用 bytes(s, encoding=...)str(b, encoding=...)
  • str 一样,bytes 类型是不可变的。 有一个单独的 mutable 类型来保存缓冲的二进制数据,bytearray。 几乎所有接受 bytes 的 API 也接受 bytearray。 可变 API 基于 collections.MutableSequence
  • 原始字符串文字中的所有反斜杠都按字面解释。 这意味着未对原始字符串中的 '\U''\u' 转义进行特殊处理。 例如,r'\u20ac' 在 Python 3.0 中是 6 个字符的字符串,而在 2.6 中,ur'\u20ac' 是单个“欧元”字符。 (当然,此更改仅影响原始字符串文字;欧元字符在 Python 3.0 中为 '\u20ac'。)
  • 内置的 basestring 抽象类型已被删除。 请改用 strstrbytes 类型没有足够的共同功能来保证共享基类。 2to3 工具(见下文)用 str 替换每次出现的 basestring
  • 作为文本文件打开的文件(仍然是 open() 的默认模式)总是使用编码在字符串(内存中)和字节(磁盘上)之间进行映射。 二进制文件(在 mode 参数中用 b 打开)总是使用内存中的字节。 这意味着如果使用不正确的模式或编码打开文件,I/O 可能会大声失败,而不是默默地产生不正确的数据。 这也意味着即使是 Unix 用户在打开文件时也必须指定正确的模式(文本或二进制)。 有一个平台相关的默认编码,在 Unixy 平台上可以使用 LANG 环境变量(有时也可以使用其他一些特定于平台的语言环境相关的环境变量)进行设置。 在很多情况下,但不是全部,系统默认是 UTF-8; 你永远不应该指望这个默认值。 任何读取或写入比纯 ASCII 文本更多的应用程序都应该有办法覆盖编码。 不再需要在 codecs 模块中使用编码感知流。
  • sys.stdinsys.stdoutsys.stderr 的初始值现在是 unicode-only 文本文件(即,它们是 的实例) io.TextIOBase)。 要使用这些流读取和写入字节数据,您需要使用它们的 io.TextIOBase.buffer 属性。
  • 文件名作为 (Unicode) 字符串传递给 API 并从 API 返回。 这可能会出现特定于平台的问题,因为在某些平台上文件名是任意字节字符串。 (另一方面,在 Windows 上,文件名本机存储为 Unicode。)作为一种变通方法,大多数 API(例如 open()os 模块中的许多函数)接受文件名接受 bytes 对象以及字符串,并且一些 API 有方法要求bytes 返回值。 因此,如果参数是 bytes 实例,os.listdir() 返回 bytes 实例的列表,并且 os.getcwdb() ] 将当前工作目录作为 bytes 实例返回。 请注意,当 os.listdir() 返回字符串列表时,无法正确解码的文件名将被省略,而不是引发 UnicodeError
  • 当系统提供的可用字节无法使用默认编码进行解释时,某些系统 API(如 os.environsys.argv)也会出现问题。 设置 LANG 变量并重新运行程序可能是最好的方法。
  • PEP 3138:字符串的 repr() 不再转义非 ASCII 字符。 但是,它仍然会转义 Unicode 标准中具有不可打印状态的控制字符和代码点。
  • PEP 3120:默认源编码现在是 UTF-8。
  • PEP 3131:现在允许在标识符中使用非 ASCII 字母。 (但是,除了注释中的贡献者姓名外,标准库仍然是仅 ASCII 格式的。)
  • StringIOcStringIO 模块不见了。 相反,导入 io 模块并分别对文本和数据使用 io.StringIOio.BytesIO
  • 另请参阅 Unicode HOWTO,它已针对 Python 3.0 进行了更新。


语法更改概述

本节简要概述了 Python 3.0 中的每个 语法 更改。

新语法

  • PEP 3107:函数参数和返回值注释。 这提供了注释函数参数和返回值的标准化方法。 除了可以在运行时使用 __annotations__ 属性自省之外,此类注释没有附加语义。 目的是鼓励通过元类、装饰器或框架进行实验。

  • PEP 3102:仅关键字参数。 在参数列表 中出现在 *args 之后的命名参数必须在调用中使用关键字语法指定。 您还可以在参数列表中使用一个空 * 来表示您不接受可变长度的参数列表,但您确实有仅关键字参数。

  • 在类定义中的基类列表之后允许使用关键字参数。 这被新约定用于指定元类(参见下一节),但也可用于其他目的,只要元类支持它。

  • PEP 3104非本地 语句。 使用 nonlocal x 您现在可以直接分配给外部(但非全局)范围内的变量。 nonlocal 是新的保留字。

  • PEP 3132:扩展迭代解包。 您现在可以编写诸如 a, b, *rest = some_sequence 之类的内容。 甚至 *rest, a = stuffrest 对象总是一个(可能是空的)列表; 右侧可以是任何可迭代的。 例子:

    (a, *rest, b) = range(5)

    这会将 a 设置为 0,将 b 设置为 4,并将 rest 设置为 [1, 2, 3]

  • 字典推导:{k: v for k, v in stuff}dict(stuff)意思相同,但更灵活。 (这是 PEP 274 平反。 :-)

  • 设置文字,例如 {1, 2}。 注意 {} 是一个空字典; 使用 set() 作为空集。 还支持集合理解; 例如,{x for x in stuff}set(stuff) 的含义相同,但更灵活。

  • 新的八进制文字,例如 0o720(已在 2.6 中)。 旧的八进制文字 (0720) 消失了。

  • 新的二进制文字,例如 0b1010(已经在2.6中),并且有一个新的对应内置函数,bin()

  • 字节文字以 bB 开头,并且有一个新的对应内置函数,bytes()


更改语法

  • PEP 3109PEP 3134:新的 raise 语句语法:raise [expr [from expr]]。 见下文。

  • aswith 现在是保留字。 (实际上从 2.6 开始。)

  • TrueFalseNone 是保留字。 (2.6 已经部分强制执行了对 None 的限制。)

  • except exc, var 改为 except exc as var ]。 参见 PEP 3110

  • PEP 3115:新的元类语法。 代替:

    class C:
        __metaclass__ = M
        ...

    你现在必须使用:

    class C(metaclass=M):
        ...

    不再支持模块全局 __metaclass__ 变量。 (这是一个拐杖,它可以更容易地默认为新型类,而无需从 object 派生每个类。)

  • 列表推导式不再支持语法形式 [... for var in item1, item2, ...]。 请改用 [... for var in (item1, item2, ...)]。 另请注意,列表推导式具有不同的语义:它们更接近于 list() 构造函数内的生成器表达式的语法糖,尤其是循环控制变量不再泄漏到周围的作用域中。

  • 省略号 (...) 可以在任何地方用作原子表达式。 (以前它只允许在切片中。)此外,它 必须 现在拼写为 ...。 (以前它也可以拼写为 . . .,这仅仅是语法上的一个意外。)


删除的语法

  • PEP 3113:删除元组参数解包。 你不能再写def foo(a, (b, c)): ...。 请改用 def foo(a, b_c): b, c = b_c
  • 删除了反引号(改用 repr())。
  • 移除了 <>(改为使用 !=)。
  • 移除关键字:exec() 不再是关键字; 它仍然是一个函数。 (幸运的是,2.x 中也接受了函数语法。)还要注意 exec() 不再接受流参数; 您可以使用 exec(f.read()) 代替 exec(f)
  • 整数文字不再支持尾随 lL
  • 字符串文字不再支持前导 uU
  • from module import * 语法只允许在模块级别,不再在函数内部。
  • 相对导入唯一可接受的语法是 from .[module] import name。 所有不以 . 开头的 import 形式都被解释为绝对导入。 (PEP 328)
  • 经典课没了。


Python 2.6 中已经存在的变化

由于许多用户可能直接从 Python 2.5 跳转到 Python 3.0,因此本节提醒读者最初为 Python 3.0 设计但后来移植到 Python 2.6 的新功能。 应查阅 Python 2.6 中的新增功能 中的相应部分以获得更长的描述。


图书馆变化

由于时间限制,本文档没有详尽地涵盖对标准库的非常广泛的更改。 PEP 3108 是对库的主要更改的参考。 这是一个胶囊评论:

  • 许多旧模块被删除。 一些,如 gopherlib(不再使用)和 md5(由 hashlib 取代),已经被 PEP 4 弃用]。 由于取消了对 Irix、BeOS 和 Mac OS 9 等各种平台的支持(请参阅 PEP 11),其他部分被删除。 由于缺乏使用或因为存在更好的替代品,一些模块也被选择在 Python 3.0 中删除。 有关详尽列表,请参阅 PEP 3108

  • bsddb3 包被删除,因为随着时间的推移,由于测试的不稳定性和 Berkeley DB 的发布时间表,它在核心标准库中的存在已被证明是核心开发人员的一个特殊负担。 但是,该软件包仍然有效,外部维护在 https://www.jcea.es/programacion/pybsddb.htm。

  • 一些模块被重命名是因为它们的旧名称违反了 PEP 8,或者其他各种原因。 这是清单:

    旧名

    新名字

    _winreg

    温格

    配置解析器

    配置解析器

    复制注册表

    复制注册表

    队列

    队列

    套接字服务器

    套接字服务器

    标记库

    _标记库

    代表

    复制库

    test.test_support

    测试支持

  • Python 2.x 中的一个常见模式是用纯 Python 实现模块的一个版本,以及作为 C 扩展实现的可选加速版本; 例如,picklecPickle。 这给这些模块的每个用户带来了导入加速版本和使用纯 Python 版本的负担。 在 Python 3.0 中,加速版本被视为纯 Python 版本的实现细节。 用户应该始终导入标准版本,它会尝试导入加速版本并回退到纯 Python 版本。 pickle / cPickle 对接受了这种处理。 profile 模块在 3.1 的列表中。 StringIO模块已经变成了io模块中的一个类。

  • 一些相关的模块已被分组到包中,通常子模块名称已被简化。 由此产生的新包是:

    • dbm (anydbm, dbhash, dbm, dumbdbm, gdbm, whichdb )。

    • htmlHTMLParserhtmlentitydefs)。

    • httphttplibBaseHTTPServerCGIHTTPServerSimpleHTTPServerCookiecookielib) .

    • tkinter(除 turtle 外的所有 Tkinter 相关模块)。 turtle的目标受众并不真正关心tkinter。 另请注意,从 Python 2.6 开始,turtle 的功能已大大增强。

    • urlliburlliburllib2urlparserobotparse)。

    • xmlrpcxmlrpclibDocXMLRPCServerSimpleXMLRPCServer)。

PEP 3108 未涵盖的对标准库模块的一些其他更改:

  • 杀死 sets。 使用内置的 set() 类。
  • sys 模块的清理:移除 sys.exitfunc()sys.exc_clear()sys.exc_typesys.exc_valuesys.exc_traceback。 (注意 sys.last_type 等。 保持。)
  • array.array 类型的清理:read()write() 方法消失了; 改用 fromfile()tofile()。 此外,数组的 'c' 类型代码也消失了——使用 'b' 表示字节或 'u' 表示 Unicode 字符。
  • operator 模块的清理:移除了 sequenceIncludes()isCallable()
  • thread模块的清理:acquire_lock()release_lock()不见了; 改用 acquire()release()
  • random 模块的清理:删除了 jumpahead() API。
  • new 模块不见了。
  • 功能 os.tmpnam()os.tempnam()os.tmpfile() 已被移除,以支持 tempfile 模块。
  • tokenize 模块已更改为使用字节。 主要入口点现在是 tokenize.tokenize(),而不是 generate_tokens。
  • string.letters 和它的朋友(string.lowercasestring.uppercase)不见了。 使用 string.ascii_letters 等。 反而。 (删除的原因是 string.letters 和朋友有特定于语言环境的行为,这对于这些名字很吸引人的全局“常量”来说是个坏主意。)
  • 将模块 __builtin__ 重命名为 builtins(删除下划线,添加一个“s”)。 大多数全局命名空间中的 __builtins__ 变量没有改变。 要修改内置函数,您应该使用 builtins,而不是 __builtins__


PEP 3101:一种新的字符串格式化方法

  • 内置字符串格式化操作的新系统取代了 % 字符串格式化操作符。 (但是,仍然支持 % 运算符;它将在 Python 3.1 中被弃用,并在稍后从语言中删除。)阅读 PEP 3101全勺。


对异常的更改

用于引发和捕获异常的 API 已被清理,并添加了新的强大功能:

  • PEP 352:所有异常都必须(直接或间接)从 BaseException 派生。 这是异常层次结构的根。 这不是新的建议,但从 BaseException 继承的 要求 是新的。 (Python 2.6 仍然允许引发经典类,并且没有限制您可以捕获的内容。)因此,字符串异常终于真正彻底地消亡了。

  • 几乎所有的异常实际上都应该从 Exception 派生出来; BaseException 仅应用作仅应在顶层处理的异常的基类,例如 SystemExitKeyboardInterrupt。 处理除后一类之外的所有异常的推荐习惯用法是使用 except Exception

  • StandardError 被移除。

  • 异常不再表现为序列。 请改用 args 属性。

  • PEP 3109:引发异常。 您现在必须使用 raise Exception(args) 而不是 raise Exception, args。 此外,您不能再明确指定回溯; 相反,如果您 来执行此操作,您可以直接分配给 __traceback__ 属性(见下文)。

  • PEP 3110:捕获异常。 您现在必须使用 except SomeException as variable 而不是 except SomeException, variable。 此外,当保留 except 块时,会显式删除 变量

  • PEP 3134:异常链。 有两种情况:隐式链接和显式链接。 当在 exceptfinally 处理程序块中引发异常时,会发生隐式链接。 这通常是由于处理程序块中的错误而发生的; 我们称之为 次要 异常。 在这种情况下,原始异常(正在处理的)被保存为次要异常的 __context__ 属性。 使用以下语法调用显式链接:

    raise SecondaryException() from primary_exception

    (其中 primary_exception 是任何产生异常对象的表达式,可能是先前捕获的异常)。 在这种情况下,主要异常存储在次要异常的 __cause__ 属性中。 发生未处理的异常时打印的回溯遍历 __cause____context__ 属性链,并为链的每个组件打印单独的回溯,主要异常位于顶部。 (Java 用户可能会认识到这种行为。)

  • PEP 3134:异常对象现在将其回溯存储为 __traceback__ 属性。 这意味着异常对象现在包含与异常有关的所有信息,并且使用 sys.exc_info() 的理由更少(尽管后者没有被删除)。

  • 当 Windows 无法加载扩展模块时,改进了一些异常消息。 例如,error code 193 现在是 %1 is not a valid Win32 application。 字符串现在处理非英语语言环境。


杂项其他更改

运算符和特殊方法

  • != 现在返回与 == 相反的结果,除非 == 返回 NotImplemented
  • “未绑定方法”的概念已从语言中删除。 将方法作为类属性引用时,您现在会得到一个普通的函数对象。
  • __getslice__()__setslice__()__delslice__()被杀。 语法 a[i:j] 现在转换为 a.__getitem__(slice(i, j))(或 __setitem__()__delitem__(),分别用作分配或删除目标时)。
  • PEP 3114:标准的 next() 方法已重命名为 __next__()
  • __oct__()__hex__() 特殊方法被删除 - oct()hex() 现在使用 __index__() 来转换参数为整数。
  • 删除了对 __members____methods__ 的支持。
  • 名为 func_X 的函数属性已重命名为使用 __X__ 形式,在函数属性命名空间中为用户定义的属性释放了这些名称。 即,func_closurefunc_codefunc_defaultsfunc_dictfunc_docfunc_globalsfunc_name ] 重命名为 __closure____code____defaults____dict____doc____globals__ __name__,分别。
  • __nonzero__() 现在是 __bool__()


内置函数

  • PEP 3135:新的 super()。 您现在可以不带参数调用 super() 并且(假设这是在 class 语句中定义的常规实例方法中)将自动选择正确的类和实例。 使用参数,super() 的行为不变。
  • PEP 3111raw_input() 重命名为 input()。 也就是说,新的 input() 函数从 sys.stdin 中读取一行,并在删除尾随换行符的情况下返回它。 如果输入过早终止,它会引发 EOFError。 要获得 input() 的旧行为,请使用 eval(input())
  • 添加了一个新的内置函数 next() 来调用对象的 __next__() 方法。
  • round() 函数舍入策略和返回类型已更改。 确切的中途情况现在四舍五入到最接近的偶数结果,而不是远离零。 (例如,round(2.5) 现在返回 2 而不是 3。)round(x[, n]) 现在委托给 x.__round__([n]) 而不是总是返回一个浮点数。 它通常在使用单个参数调用时返回一个整数,在使用两个参数调用时返回与 x 相同类型的值。
  • intern() 移至 sys.intern()
  • 移除:apply()。 使用 f(*args) 代替 apply(f, args)
  • 删除了 callable()。 您可以使用 isinstance(f, collections.Callable) 代替 callable(f)operator.isCallable() 功能也没有了。
  • 移除 coerce()。 既然经典类已经消失,这个函数就不再有用了。
  • 移除 execfile()。 使用 exec(open(fn).read()) 代替 execfile(fn)
  • 移除了 file 类型。 使用 open()。 现在有几种不同类型的流可以在 io 模块中返回。
  • 移除 reduce()。 如果确实需要,请使用 functools.reduce(); 然而,在 99% 的情况下,显式的 for 循环更具可读性。
  • 移除 reload()。 使用 imp.reload()
  • 已移除。 dict.has_key() – 改用 in 运算符。


构建和 C API 更改

由于时间限制,这里有一个 非常 不完整的 C API 更改列表。

  • 取消了对多个平台的支持,包括但不限于 Mac OS 9、BeOS、RISCOS、Irix 和 Tru64。
  • PEP 3118:新的缓冲区 API。
  • PEP 3121 :扩展模块初始化和终结。
  • PEP 3123:使PyObject_HEAD符合标准C。
  • 不再为受限执行提供 C API 支持。
  • PyNumber_Coerce()PyNumber_CoerceEx()PyMember_Get()PyMember_Set() C API 被删除。
  • 新的 C API PyImport_ImportModuleNoBlock(),与 PyImport_ImportModule() 类似,但不会阻塞导入锁(而是返回错误)。
  • 重命名布尔转换 C 级插槽和方法:nb_nonzero 现在是 nb_bool
  • 从 C API 中删除了 METH_OLDARGSWITH_CYCLE_GC


表现

3.0 泛化的最终结果是 Python 3.0 运行 pystone 基准测试大约比 Python 2.5 低 10% s。 最有可能的最大原因是删除了小整数的特殊情况。 有改进的空间,但会在 3.0 发布后发生!


移植到 Python 3.0

要将现有的 Python 2.5 或 2.6 源代码移植到 Python 3.0,最佳策略如下:

  1. (先决条件:)从出色的测试覆盖率开始。

  2. 移植到 Python 2.6。 这应该不会比从 Python 2.x 到 Python 2.(x+1) 的平均端口更多的工作。 确保所有测试都通过。

  3. (仍在使用2.6:)打开-3命令行开关。 这会启用有关将在 3.0 中删除(或更改)的功能的警告。 再次运行您的测试套件,并修复您收到警告的代码,直到没有警告为止,并且您的所有测试仍然通过。

  4. 在源代码树上运行 2to3 源到源转换器。 (有关此工具的更多信息,请参阅 2to3 - 自动 Python 2 到 3 代码翻译。)在 Python 3.0 下运行翻译结果。 手动修复任何剩余的问题,修复问题直到所有测试再次通过。

不建议尝试编写在 Python 2.6 和 3.0 下都运行不变的源代码; 你必须使用非常扭曲的编码风格,例如 避免 print 语句、元类等等。 如果您正在维护一个需要同时支持 Python 2.6 和 Python 3.0 的库,最好的方法是通过编辑 2.6 版本的源代码并再次运行 2to3 转换器来修改上面的第 3 步,而不是编辑3.0 版本的源代码。

有关将 C 扩展移植到 Python 3.0,请参阅 将扩展模块移植到 Python 3