当前位置: 首页 > 面试题库 >

准备从Python 2.x转换为3.x

谢雅珺
2023-03-14
问题内容

众所周知(希望如此),Python
3逐渐开始取代Python2.x。当然,要移植大多数现有代码还需要很多年,但是现在我们可以在2.x版本的代码中做一些事情,以使切换更加容易。

显然,看看3.x的新功能会有所帮助,但是我们现在可以做些什么,以使即将进行的转换更加轻松(并在需要时更容易将更新输出到并发版本)?我特别考虑的是可以启动脚本的行,这将使Python的早期版本与3.x更加相似,尽管也欢迎其他习惯。

我能想到的最明显的添加到脚本顶部的代码是:

from __future__ import division
from __future__ import print_function
try:
    range = xrange
except NameError:
    pass

我能想到的最明显的习惯是 "{0} {1}!".format("Hello", "World") 字符串格式化。

还有其他需要注意的方面和好习惯吗?


问题答案:

微级别更改和2to3无法充分解决的最大问题是将默认字符串类型从字节更改为Unicode。

如果您的代码需要对编码和字节I /
O进行任何操作,则需要大量的人工工作才能正确转换,以便必须为字节的内容保留为字节,并在正确的阶段正确解码。您会发现某些字符串方法(尤其是format())和库调用需要Unicode字符串,因此您可能需要额外的解码/编码周期才能将字符串用作Unicode,即使它们实际上只是字节。

某些Python标准库模块已使用2to3进行了粗略转换,而没有适当注意字节/ unicode
/编码问题,因此这无济于事,因此它们自己在适当的字符串类型上会犯错误。其中一些问题已被解决,但是至少从Python
3.0到3.2,您将面临来自urllib,email和wsgiref之类的软件包的混乱和潜在的错误行为,这些软件包需要了解字节编码。

您可以在每次编写字符串文字时都多加注意,以缓解问题。u''对于本质上基于字符的任何东西,都使用字符串,b''对于真正字节的任何东西,都使用字符串,对于''无关紧要的“默认字符串”类型,或者您需要匹配库调用的字符串使用要求,请使用字符串。

不幸的是,该b''语法仅在Python 2.6中引入,因此这样做会切断早期版本的用户。

eta:

有什么不同?

天啊。好…

字节包含一个介于0到255之间的值,并且可以表示二进制数据(例如,图像的内容)或某些文本的负载,在这种情况下,必须为如何映射一组数据选择标准。字符放入那些字节。这些大多数“编码”标准都以相同的方式将普通的“
ASCII”字符集映射到字节0至127中,因此在Python 2中使用字节字符串进行纯ASCII文本处理通常是安全的。

如果要在字节字符串中使用ASCII设置之外的任何字符,则会遇到麻烦,因为每种编码都会将不同的字符集映射到其余的字节值128–255中,并且大多数编码不能将每个可能的字符到字节。这是所有这些问题的根源,在这些问题中,您从一个区域设置将文件加载到另一区域设置的Windows应用程序中,并且所有带有重音或非拉丁字母的字母都变成了错误的字母,从而造成了不可读的混乱。(又名“
mojibake”。)

还有“多字节”编码,通过使用多个字节存储每个字符,尝试将更多字符放入可用空间。这些字符是为东亚语言环境引入的,因为有太多的汉字。但是还有UTF-8,这是一种设计更好的现代多字节编码,可以容纳
每个 字符。

如果您正在处理多字节编码的字节字符串,那么今天可能会这样做,因为UTF-8的使用非常广泛。实际上,在现代应用程序中不应使用任何其他编码-
这样,除了跟踪使用的编码方式之外,还有更多的问题。len()会告诉您以字节为单位的长度,而不是以字符为单位的长度,如果您开始索引和更改字节,则很有可能将一个多字节序列分成两个部分,从而生成无效序列并使所有内容混乱。

因此,Python
1.6和更高版本具有本机Unicode字符串(拼写为u'something'),其中字符串中的每个单位都是字符,而不是字节。您可以对len()它们进行切片,替换,对它们进行正则表达式,它们将始终表现适当。对于文本处理任务,它们无疑是更好的,这就是为什么Python
3将它们设置为默认字符串类型(而不必在u之前加上'')的原因。

问题在于,许多现有接口(例如Windows或HTTP或SMTP以外的OS上的文件名)主要基于字节,并使用了一种指定编码的单独方法。因此,当您处理需要字节的组件时,必须注意将unicode字符串正确编码为字节,而在Python
3中,您将必须在不需要的地方明确地执行此操作。

内部实现细节是Unicode字符串在内部每个单元占用“两个字节”的存储空间。您永远不会看到该存储空间;您不应该以字节为单位来考虑它。无论Python选择如何在内存中表示它们,您正在使用的单元在概念上都是字符。

…在旁边:

这不是真的。在像Windows版本一样的Python的“窄版本”上,Unicode字符串的每个单元从技术上讲都不是字符,而是UTF-16“代码单元”。对于基本多语言平面中的字符,从0x0000–0xFFFF不会有任何区别,但是如果您使用的是16位范围之外的字符,则“星形平面”中的字符会占用分割成两个单位而不是一个单位,并且再次切成片时会有分割字符的风险。

这是非常糟糕的,并且是因为Windows(以及Java等其他语言)在Unicode增长到超过65,000个字符的限制之前就将UTF-16作为一种内存中存储机制而成立的。但是,仍然很少使用这些扩展字符,Windows上的任何人都会习惯于使用它们来破坏许多应用程序,因此对您来说并不重要。

在“广泛构建”中,Unicode字符串由真实字符“代码点”单元组成,因此,即使在BMP之外的扩展字符也可以始终如一地轻松处理。为此付出的代价是效率:每个字符串单元占用内存中的四个字节。



 类似资料:
  • 问题内容: 这是我先前问题的跟进,我正在使用Senthil Kumaran建议的2to3工具 似乎工作正常,但没有涉及到这一部分: 3.2中应该是什么样子? 编辑: 从下面的答案的变化是好的,2to3现在似乎工作正常。但是,在setup.py构建中,我现在看到以下错误,请参见我的新问题。 问题答案: LexError后删除逗号。可以在Python 2和Python 3中使用。 在Python 2中

  • Python的3​​.0版本,常被称为Python 3000,或简称Py3k。相对于Python的早期版本,这是一个较大的升级。 为了不带入过多的累赘,Python 3.0在设计的时候没有考虑向下相容。 许多针对早期Python版本设计的程式都无法在Python 3.0上正常执行。 为了照顾现有程式,Python 2.6作为一个过渡版本,基本使用了Python 2.x的语法和库,同时考虑了向Pyt

  • Python的3​​.0版本,常被称为Python 3000,或简称Py3k。相对于Python的早期版本,这是一个较大的升级。 为了不带入过多的累赘,Python 3.0在设计的时候没有考虑向下相容。 许多针对早期Python版本设计的程式都无法在Python 3.0上正常执行。 为了照顾现有程式,Python 2.6作为一个过渡版本,基本使用了Python 2.x的语法和库,同时考虑了向Pyt

  • 本文向大家介绍Python2.x与3​​.x版本有哪些区别,包括了Python2.x与3​​.x版本有哪些区别的使用技巧和注意事项,需要的朋友参考一下 Python的3​​.0版本,常被称为Python 3000,或简称Py3k。相对于Python的早期版本,这是一个较大的升级。 为了不带入过多的累赘,Python 3.0在设计的时候没有考虑向下相容。 许多针对早期Python版本设计的程式都无法

  • 使用TYPE_MAGNETOMETER传感器时,可以获得与设备方向相关的磁场强度的X,Y,Z值。我想得到的是将这些值转换为全局参考系,澄清:用户获取设备,测量这些值,而不是围绕任何轴旋转设备一定程度并获得~相同的值。请在下面找到类似的问题: 获取全局坐标中的磁场值 如何获得独立于设备旋转的磁场矢量?在这个答案中描述了示例解决方案(它是线性加速度,但我认为这没关系):https://stackove

  • 本文向大家介绍深入浅析Python2.x和3.x版本的主要区别,包括了深入浅析Python2.x和3.x版本的主要区别的使用技巧和注意事项,需要的朋友参考一下 版本说明 Python 3.0在设计的时候没有考虑向较早版本相容 Python 2.6作为一个过渡版本,基本使用了Python 2.x的语法和库,同时考虑了向Python 3.0的迁移,允许使用部分Python 3.0的语法与函数。   除

  • 本文向大家介绍Windows下使Python2.x版本的解释器与3.x共存的方法,包括了Windows下使Python2.x版本的解释器与3.x共存的方法的使用技巧和注意事项,需要的朋友参考一下 Python2 和 Python3 是不兼容的,如果碰到无法升级到 Python2 代码,或者同事中有坚守 Python2 阵营的情况,就要考虑 Python2 和 Python3 在系统中共存的情况。

  • 这一章,主要是为了把权限模型给准备好 User 用户表 Role 角色表 Permission 权限表 User -- Role 多对多 User -- Permission 多对多 Role -- Permission 多对多