【翻译】 迁移到Python 3

2023-10-26

本文由LWN用户为您带来

LWN.net的订阅者使得这篇文章--以及它周围的一切--成为可能。 如果您喜欢我们的内容,请购买订阅,使下一组文章成为可能。

2011年2月9日

本文由Ian Ward提供

Python 3.0于2008年底发布,但到目前为止,只有相对较少的软件包更新到支持最新版本;大多数Python软件仍然只支持Python 2。 Python 3 引入了对 Unicode 和字符串处理、模块导入、整数表示和除法、打印语句以及其它一些不同之处的修改。 本文将介绍从 Python 2 移植到 Python 3 时最容易引起问题的一些变化,并介绍管理同时支持两个主要版本的单一代码库的一些策略。

Python 3 中的改动最初是被称为 "Python 3000 "的计划的一部分,这是一个关于语言改动的玩笑,这些改动只能在遥远的将来完成。 这些修改列出了 Python 语言中不一致的地方和不方便的设计,这些修改本来是很好修复的,但是因为修复它们意味着破坏所有现有的 Python 代码,所以只能等待。最终,Python 开发者们决定用一个真正稳定的版本来修复这些问题,并接受这样一个事实:大多数软件包和用户需要几年的时间来完成转换。

那么有什么大不了的呢?

最大的变化是 Python 3 处理字符串的方式。 Python 2 有 8 位字符串和 Unicode 文本,而 Python 3 有 Unicode 文本和二进制数据。 在 Python 2 中,您可以自由地使用字符串和 Unicode 文本,使用任何一种类型的参数,并且在必要时自动转换。 这很好,直到您在字符串中得到一些 8 位数据,而某个函数 (在您的代码中的任何地方或您正在使用的库的深处) 需要 Unicode 文本。 然后,一切都崩溃了。 Python 2 试图将字符串解码为 7 位 ASCII 以获得 Unicode 文本,这就给开发者,或者更糟糕的是给最终用户留下了这些问题:

    Traceback (most recent call last): ... UnicodeDecodeError: 'ascii' codec can't decode byte 0xf4 in position 3: \ ordinal not in range(128)

在 Python 3 中没有更多的自动转换,缺省几乎在所有地方都是 Unicode 文本。 Python 2 将'all\xf4'作为一个有 4 个字节的 8 位字符串,而 Python 3 将相同的字面作为 Unicode 文本,U+00F4 作为第四个字符。

在 Python 3 中以文本模式打开的文件 (缺省值,包括sys.stdinsys.stdoutsys.stderr),从read()返回 Unicode 文本,并期望传递 Unicode 文本给write()。 在二进制模式下打开的文件只操作二进制数据。 这个变化对 Linux 和其它类 Unix 操作系统中的 Python 用户的影响比对 Windows 和 Mac 用户的影响更大 - 在 Linux 上的 Python 2 中,以二进制模式打开的文件与以文本模式打开的文件几乎没有区别,而 Windows 和 Mac 用户已经习惯了 Python 在文本模式下至少要换行。

这意味着许多过去 "工作 "的代码 (这里的 "工作 "是指仅用于 ASCII 文本) 现在被破坏了。 但是,一旦这些代码被更新以正确处理哪些输入和输出是文本编码,哪些是二进制编码,那么那些母语或名称不符合ASCII码的人就可以轻松地使用这些代码了。 这是一个非常好的结果。

Python 3 用于二进制数据的bytes类型与 Python 2 的 8 位字符串有很大不同。 Python 2.6 和更高版本将bytes定义为与str类型相同,这有点奇怪,因为接口发生了很大的变化:

    >>> bytes([2,3,4]) # Python 2 '[2, 3, 4]' >>> [x for x in 'abc'] ['a', 'b', 'c

在 Python 3 中,b''用于字节字面量:

    >>> bytes([2,3,4]) # Python 3 b'\x02\x03\x04' >>> [x for x in b'abc'] [97, 98, 99]

Python 3 的字节类型可以被看作是一个不变的列表,其值在 0 到 255 之间。 这对于处理二进制数据时的位运算和其它数字运算很方便,但它与 Python 2 程序员期望的长度为 1 的字符串有很大不同。

整数也发生了变化。 长整数和普通整数之间没有区别,sys.maxint也消失了。 整数除法也发生了变化。 任何有 Python (或 C) 背景的人都会告诉你:

    >>> 1/2 0 >>> 1.0/2 0.5

但不再是这样了。 幸运的是,Python 2.2 和更高版本有一个除法运算符(//)。 使用它,您可以确定结果是整数。

我要指出的最后一个大变化是比较。 在 Python 2 中,比较(<, <=,>=,>) 总是在所有对象之间定义。 当没有定义显式排序时,一种类型的所有对象将被任意地认为大于或小于另一种类型的所有对象。 因此,您可以对一个混合了多种类型的列表进行排序,然后将所有不同类型的对象归为一组。 但是大多数时候,您真的不想对不同类型的对象排序,这个特性只是隐藏了一些令人讨厌的 bug。

Python 3 现在会在比较不兼容类型的对象时引发TypeError,这是它应该做的。 注意所有类型的相等(==,!=) 仍然被定义。

模块导入发生了变化。 在 Python 2 中,导入时首先搜索包含源文件的目录 (称为 "相对导入"),然后依次尝试系统路径中的目录。 在 Python 3 中,相对导入必须是显式的:

    from . import my_utils

在 Python 3 中,print语句变成了一个函数。 这段 Python 2 代码向sys.stderr打印一个字符串,在字符串末尾用空格代替换行:

    import sys print >>sys.stderr, 'something bad happened:'、

变为

    import sys print('something bad happened:', end=' ', file=sys.stderr)

这些只是一些最大的变化。 完整列表在这里

这个列表非常庞大。 我该如何处理这些呢?

幸运的是,Python 附带的2to3工具处理了大量的不兼容问题。 2to3使用 Python 2 源代码并执行一些自动替换,以准备代码在 Python 3 中运行。Print 语句变成了函数,Unicode 文本字面量去掉了"u"前缀,相对导入变得显式,等等。

不幸的是,其余的修改需要手工完成。

2to3 的帮助下,维护一个可以在 Python 2 和 Python 3 中工作的单一代码库是合理的。 在我的库"Urwid "中,我的目标是 Python 2.4 及以上版本,这是我使用的兼容性代码的一部分。 当你真的需要写一些在 Python 2 和 Python 3 中使用不同路径的代码时,用"if PYTHON3:" 语句来明确一下是很好的:

    import sys PYTHON3 = sys.version_info >= (3, 0) try:# 为 Python 2.4, 2.5 定义字节 bytes = bytes except NameError: bytes = str if PYTHON3: # 用于创建字节字符串 B = lambda x: x.encode('latin1') else: B = lambda x: x

字符串处理和字面字符串是最常见的需要更新的地方。 一些指导原则:

  • 在源代码中的所有字面文本中使用Unicode字面(u'')。 这样您的意图就很明确,并且在 Python 3 中的行为也是一样的(2to3将把它们转换成普通的文本字符串)。

  • 如果您支持的 Python 版本早于 2.6,则对所有字面的字节字符串使用字节字面(b'') 或上面的B()函数。 B()利用 Unicode 的前 256 个码位映射到 Latin-1 的事实,从 Unicode 文本创建二进制字符串。

  • 只有在 Python 2 期望使用 8 位字符串,而 Python 3 期望使用 Unicode 文本的情况下,才使用普通字符串 ('') 。 这些情况包括属性名、标识符、docstrings 和__repr__返回值。

  • 记录您的函数是接受字节还是 Unicode 文本,并防止传入错误的类型 (例如assert isinstance(var, unicode)),或者如果您必须接受两种类型,立即转换为 Unicode 文本。

在您的源代码中明确地将文本标记为文本,二进制标记为二进制,这可以作为文档,并且可以防止您编写的代码在 Python 3 下运行时失败。

跨 Python 版本处理二进制数据有几种方法。 如果用data[i:i+1] 替换所有单独的字节访问,例如 data[i],那么在 Python 2 和 Python 3 中都会得到长度为-1 的字节串。 然而,我更喜欢遵循 Python 3 的习惯,将字节字符串作为整数列表来处理,并使用一些更兼容的代码:

    if PYTHON3: # 用于操作字节 ord2 = lambda x: x chr2 = lambda x: bytes([x]) else: ord2 = ord chr2 = chr

在 Python 2 或 Python 3 中,ord2返回一个字节的序号值 (在 Python 2 或 Python 3 中,它是一个无操作符),而chr2转换回一个字节字符串。 根据你处理二进制数据的方式,对整数序号值而不是长度为-1 的字节字符串进行操作可能会更快。

Python "doctests" 是出现在函数、类和模块文档文本中的测试代码片段。 测试代码类似于一个交互式的 Python 会话,包括代码的运行和输出。 对于简单的函数来说,这种测试通常就足够了,而且是很好的文档。 然而,Doctests对在同一个代码库中支持Python 2和Python 3提出了挑战。

2to3可以以与源代码其它部分相同的方式转换 doctest 代码,但它不会触及预期输出。 Python 2 会在长整型输出的末尾加上一个 "L",在 Unicode 字符串前面加上一个 "u",这些在 Python 3 中都不会出现,但是打印值的工作方式是一样的。 确保从 doctests 运行的其它代码一直输出相同的文本,如果不能,你可以在输出中使用ELLIPSIS标志和... 来掩盖微小的差异。

你还需要做一些简单的修改,包括

  • 在所有需要底层划分的地方使用//(如上所述)。

  • BaseException 派生异常类。

  • 在 my_dict 中使用k而不是my _ dict.has_key(k)

  • 使用my_list.sort(key=custom_key_fn)代替 my_list.sort( custom _sort)。

  • 使用distribute代替 Setuptools。

有两个额外的资源可能会有帮助:将 Python 代码移植到 3.0编写向前兼容的 Python 代码

如果我做了所有这些,对我有什么好处呢?

Python 3 毫无疑问是比 Python 2 更好的语言。 许多刚开始学习 Python 3 的人,尤其是专有操作系统的用户,都会从 Python 3 开始。更多的 Python 2 用户对 Python 3 感兴趣,但他们使用的代码或库让他们望而却步。

通过在应用程序或库中添加 Python 3 支持,您可以帮助他们:

  • 使刚开始使用 Python 3 的新用户可以使用它

  • 鼓励现有用户采用它,因为这不会阻止他们以后切换到 Python 3

  • 清理文本和二进制数据的模糊使用,并发现相关的 bug

作为一个小奖励,这些软件可以被列在Python Packaging Index 中支持Python 3 的软件包中,只需在首页点击一下即可。

许多流行的Python软件包还没有进行转换,但它肯定在每个人的雷达上。 我很幸运。 社区成员已经完成了将我的库移植到 Python 3 的大部分艰苦工作,我只需要更新我的测试,并想办法让这些改变也能在旧版本的 Python 上运行。

由于 Python 2 和 Python 3 之间的巨大差异,目前在 Python 社区中存在分歧。 但是通过一些努力,这种分歧是可以弥合的。 值得付出努力。


本文索引条目
特邀文章 Ward, Ian


(登录后发表评论)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【翻译】 迁移到Python 3 的相关文章

  • 【翻译】 迁移到Python 3

    本文由LWN用户为您带来LWN net的订阅者使得这篇文章 以及它周围的一切 成为可能 如果您喜欢我们的内容 请购买订阅 使下一组文章成为可能 2011年2月9日 本文由Ian Ward提供 Python 3 0于2008年底发布 但到目前
  • 【翻译】 用纸质电路增加开源的包容性

    你知道吗 LWN net是一份由订阅者支持的出版物 我们依靠订阅者来维持整个运作 请通过购买订阅来帮助我们 让LWN继续在网上运行 作者 Jonathan Corbet 2018年1月30日 linux conf au 开源软件有一个包容性
  • 关于Postman无法显示中文的解决方案(翻译)

    在使用Postman时很多人因为界面是纯英文的感到很头疼 会面临不知道什么意思及界面看不懂的情况 于是出现了需要将界面汉化翻译过来的需求 但从实际工作经验来讲 个人还是比较喜欢看英文界面的 可能也是看习惯了导致的吧 本文以两种方式帮助读者理
  • 冰羚中间件 RouDi usage-guide.md翻译

    内容 内容 配置RouDi Configuring RouDi RouDi可以支持读取从一个配置文件中读取mempool config 如果需要支持这个特性 CMake的编译选项中需要使用 DTOML CONFIG on mempool c
  • 【翻译】RFP有什么问题?

    科技行业充斥着首字母缩略词和缩写 有时会引发强烈的反应 RfP这些字母总是让我在黯然神伤和极度沮丧之间摇摆不定 为什么呢 因为征求建议书的过程突出了我们采购和交付软件和基础设施的方式是如何被打破的 从表面上看 传统的提案申请程序是非常合理的
  • 【翻译】 如何应对内核警告?

    LWN net需要你 没有订阅者 LWN就根本不存在 请考虑注册订阅 帮助LWN继续出版 作者 Jonathan Corbet 2021年11月18日 内核在内部提供了许多宏 允许代码在出错时产生警告 然而 它并没有提供很多关于警告发出时应
  • 各国语言对应翻译表

    为了工作方便 自己做了一个地区语言的英文翻译 让自己可以更快的找到自己需要的地方 同时 分享给大家 谢谢 中文 各国语言 翻译 序号 中文 翻译 1 阿尔巴尼亚语 2 阿拉伯语 3 阿姆哈拉语 4 阿塞拜疆语 Az rbaycan 5 爱尔
  • 人工智能革命:超级智能之路(上)

    这篇文章翻译于Tim Urban大神的 The AI Revolution 的系列文章 下面让我们一起领略一下Tim Urban大神理解的人工智能革命是怎样的吧 文章目录 遥远的未来 即将到来 超级智能之路 人工智能 我们目前在哪里 一个在
  • 【python】20行代码实现有道翻译api接口调用

    文章目录 1 目标站点 2 完整代码 3 测试样例 3 1 测试样例 汉译英 3 2 测试样例 英译汉 4 调用文档 4 1 接口地址 4 2 请求方法 4 3 请求参数 4 4 请求示例 4 5 成功响应 5 接口分析 6 相关推荐 1
  • 【翻译】我们能从英国教育考试院的算法失败中学到什么?

    如果你想找一个表面上聪明的人是如何不小心把别人的生活搞得一团糟的例子 那就看看去年英国公开考试的情况吧 简而言之 政府认识到科维德 19的威胁 取消了英国学生的公开考试 在寻求另一种评分方法时 政府及其教育监管机构可以说是由于无知或选择而违
  • 【翻译】 2.6 中的 4K 堆栈 [发布于 2004 年 5 月 12 日,作者:corbet

    传统上 Linux 内核在大多数架构上都使用 8KB 内核堆栈 该堆栈必须满足系统调用可能产生的任何调用序列 以及可能同时调用的任何 硬或软 中断处理程序的需要 实际上 在稳定的内核中 堆栈溢出的情况几乎闻所未闻 内核开发人员早已学会避免使
  • 【翻译】为什么你现在比以往更需要混沌工程?

    大约一年前 像餐馆和杂货店这样的实体店正争先恐后地设置送货和路边取货 他们中的很多人都在生产中使用混乱工程 在推出新功能和服务之前迅速寻找失败的原因 教育平台也是如此 在短短一周的时间里 从 好的 变成了 绝对必要 企业混沌工程平台 Gre
  • 【翻译】 一个新的暂停/休眠的基础设施

    LWN订阅者的好处订阅LWN的主要好处是帮助我们继续出版 但除此之外 订阅者可以立即获得所有的网站内容和获得一些额外的网站功能 请今天就注册吧 作者 Jonathan Corbet 2008年3月19日 在参加会议时 你们的编辑多年来一直注
  • csharp:百度翻译

    参考 http api fanyi baidu com api trans product index http developer baidu com wiki index php title E5 B8 AE E5 8A A9 E6 9
  • Kotlin Lazy vs Lateinit 属性. 何时使用哪个属性?

    原文链接 Kotlin提供了许多很棒的特性 我们可以利用这些功能 快速构建高质量的应用程序 在所有这些特性中 lateinit 和 lazy 是重要的初始化属性 有必要知道何时使用 lateinit 以及何时使用 lazy 初始化 late
  • 【翻译】软件表现不佳,未来取决于这种情况的改变

    如果一件事不能永远进行下去 它就不会 赫伯 斯坦法则 科技行业的未来会是什么样子 从现在到2030年 我们所有人面临的挑战不再是我们将如何说服世界 或更直接地说 我们的老板或客户 成为碳零 无论我们是否愿意 这都会到来 我们的新问题是 作为
  • 【翻译】如何使混合型会议不至于太糟糕

    混合会议又回来了 人们正在享受它们 并发现它们很有用 这是犹他大学的会议科学家约瑟夫 艾伦博士的新研究的惊人发现 这个发现让艾伦博士感到惊讶 当然也让我感到惊讶 像大多数远程团队工作的专家一样 我长期以来一直建议采用 一个远程 所有远程 的
  • Qt多国语言动态切换(含源代码)

    Qt中文国际化 含高阶做法 作者 melon 日期 2019 7 15 1 国际化需要用到的工具 lrelease exe lupdate exe linguist exe 非必须 这些工具在Qt5 12 2的bin文件夹都可以找到 lup
  • 【翻译】 zswap 压缩交换缓存

    您知道吗 LWN net 是一份由订阅者支持的出版物 我们依靠订阅者来维持整个运作 请通过订阅来帮助我们 让 LWN 继续在网络上运行 2013年2月12日 本文由 Seth Jennings 投稿 交换是性能的最大威胁之一 即使在快速固态
  • [英语学习][15][Word Power Made Easy]的精读与翻译优化

    序言 这次翻译 译者还是显得啰啰嗦嗦 另外还有一个地方没有能很准确的翻译出来 英文学习的目标 提升自身的英语水平 对日后编程技能的提升有很大帮助 希望大家这次能学到东西 同时加入我的社区讨论与交流英语相关的内容 原著英文与翻译版对照 第20

随机推荐

  • UE4平滑视角缩放

    Tick接Interp函数 用来做一个平滑过渡的值 这个值代表了一个从当前值到目标值的过渡 然后还有速度 当前值就是Target Arm Length 目标值新建一个变量 值和默认的Target Arm Length一样 下面滚轮事件 改I
  • Jenkins可持续集成_序:为什么要学习持续集成?

    阅读须知 上传的是图片 要看清楚请点击图片放大查看 版权声明 本图片来自于网络 如果涉及侵权问题 请及时联系本人删除 其他声明 本文章严禁转载 转载于 https blog 51cto com wangxiaoke 2367404
  • steam服务器连接不稳定WIN10,小编操作win10系统steam连接不稳的解决步骤

    我们的电脑都安装的是windows系统来进行办公或者娱乐 有时候会遇到一些比如win10系统steam连接不稳的问题 我们通过调查发现不少用户都碰到了win10系统steam连接不稳的问题 如果你现在找不到专业的人员来解决win10系统st
  • Android Studio 中Intel HAXM安装与模拟器创建

    Intel HAXM Hardware Accelerated Execution Manager 使用基于 Intel R Virtualization Technology VT 的硬件加速 因此需要 CPU 支持 VT 而且仅限于 I
  • C语言算法--快速排序法

    C语言算法 快速排序法 1 什么是快速排序法 快速排序 Quicksort 是一种常用的排序算法 它基于分治的思想 它的核心思想是选择一个基准元素 将数组划分为两个子数组 使得左边的子数组中的所有元素都小于等于基准元素 右边的子数组中的所有
  • 网络层IP协议

    一 IP协议的报文格式 1 4位版本号 目前只有IPv4和IPv6两个版本 所以这里只能填4或6 2 4位首部长度 4个bit能表示的最大数字是15 而这里的单位是4个字节 所以首部长度最大为15 4 60个字节 3 8位服务类型 8位服务
  • drawio 二次开发

    目的 使用drawIO 进行绘图 然后保存的时候 存到MySQL 下次打开的时候 可以遍历MySQL的所有文件 点击指定文件 可以在新的画布上展示已有的绘图 step1 开发环境 默认使用tomcat 部署 改造成spring boot 部
  • 实现水平居中的几种方式

    一 利用定位 利用绝对定位 translate div width 100px height 100px background color aquamarine position absolute top 50 left 50 transf
  • 为什么在 2023 年只使用 console.log 是一个大禁忌

    这里有 5 个必须知道的控制台对象方法和技巧 在 2023 年 您是否仍在使用它console log来满足所有 JavaScript 调试需求 是时候提升您的技能并发现 JavaScript 控制台对象的全部功能了 从console ta
  • 遇到:ValueError: not enough values to unpack (expected 2, got 1) 错误应该如何解决

    遇到 ValueError not enough values to unpack expected 2 got 1 错误通常表示你在尝试解包 unpack 一个序列时 但是序列的元素数量不够 解包操作期望的元素数量与实际的元素数量不匹配
  • python-OpenCV图像图形检测(四)

    实例下载 图形检测 检测图形轮廓 边缘检测 轮廓拟合 一 简介 图形检测是计算机视觉的一项重要功能 通过图形检测可以分析图像中可能存在的形状 然后对这些形状进行描绘 例如 搜索并绘制图像的边缘 定位图像的位置 判断图像中有没有直线 有没有圆
  • C#

    System IO Pipelines 很酷的读写数据流方式 文章目录 System IO Pipelines 很酷的读写数据流方式 前言 System IO Pipelines 是啥 有什么优点 有哪些应用场景 网络编程 文件处理 怎么使
  • C语言代码练习第四天

    目录 1 将 1 100 的数据以 10x10 矩阵格式输出 2 等差数列输出 10x10 矩阵格式 3 乘法运算格式 4 简单计算器 5 判断一个数是否可以为两个素数之和 6 二进制转为十进制 7 十进制转为二进制 8 逆置字符串 9 逆
  • Java 示例代码,它演示了如何使用 Java 实现快速排序算法

    public class QuickSort public static void quickSort int arr int left int right if left lt right int pivotIndex partition
  • 用Ubuntu服务器搭建宝塔面板访问不了怎么解决

    Ubuntu版本是20 0的 宝塔是最新版 在服务器上面部署了宝塔 却访问不了 在使用命令查询8888端口是可以访问的 然后我尝试去关闭防火墙和防火墙一些规则 然而这样并没有可以可以登录宝塔的面板 然后翻了一下官网发现 说是安全规则的问题
  • 最新微信8.0.1抢红包神器-亲测2021年2月11日可用-安卓&IOS

    概述 今晚就过年了 相信很多朋友在微信群能收到很多红包 但是过年可能吃的更重要 比如我 那么你需要如下一款软件 那就是让你在百忙之中 都不会错过任意一个红包 也就是微信的抢红包神器 我也是心血一热 想找个软件代替自己领红包 于是就找了找 并
  • kafka 安装

    二 kafka 安装 安装前提 kafka安装运行最低支持jdk7 本篇演示版本是基于jdk1 8 2 1linux 安装 kafka 官方下载地址 Apache Kafka kafka 是由scala语言编写 下载稳定版本 即前一个版本
  • 报错Uncaught (in promise) TypeError: Invalid attempt to spread non-iterable instance.

    报错Uncaught in promise TypeError Invalid attempt to spread non iterable instance In order to be iterable non array object
  • Jlink无法使用解决方法

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 一 检查问题 二 尝试重新烧录固件 1 烧录固件 后续 前言 公司使用的Jlink突然无法使用了 LED灯也不亮了 于是抱着修复Jlink的心态开始了 一 检
  • 【翻译】 迁移到Python 3

    本文由LWN用户为您带来LWN net的订阅者使得这篇文章 以及它周围的一切 成为可能 如果您喜欢我们的内容 请购买订阅 使下一组文章成为可能 2011年2月9日 本文由Ian Ward提供 Python 3 0于2008年底发布 但到目前