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

我们现在都知道(我希望),Python 3正在慢慢地替代Python 2.x.当然,在现在的大多数代码终于被移植之前,这将是很多年,但是现在我们可以在我们的2.x版本的代码中做到这一点,使得交换机变得更加轻松.

显然,在3.x中查看what’s new将是有帮助的,但是现在我们可以做些什么来使即将到来的转换更加无痛(如果需要,可以更容易地将更新输出到并发版本)?我专门考虑线路,我们可以启动我们的脚本,这将使较早版本的Python更类似于3.x,尽管其他习惯也是受欢迎的.

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

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

我可以想到的最明显的习惯是
“{0} {1}!”.格式(“Hello”,“World”)用于字符串格式化.

任何其他行和良好的习惯进入?

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

如果您的代码需要对编码和字节I / O做任何事情,则需要一大堆手动转换才能正确转换,以使必须是字节的内容保持字节,并在正确的阶段进行适当的解码.你会发现一些字符串方法(特别是format())和库调用需要Unicode字符串,所以你可能需要额外的解码/编码周期才能使用字符串作为Unicode,即使它们只是字节.

事实上,一些Python标准库模块已经使用2to3进行了粗略的转换,没有对字节/ unicode /编码问题的适当关注,所以自己对于什么字符串类型是适当的错误.其中一些正在被淘汰出局,但至少从Python 3.0到3.2,您将会遇到混乱和潜在的错误行为,如urllib,电子邮件和wsgiref等需要知道的字节编码.

你可以通过每次写一个字符串文字时小心,来改善这个问题.对于任何基于字符的字符串,使用字符串“b”“字符串”,对于“默认字符串”类型而言无关紧要,或者需要匹配库调用的字符串使用要求.

不幸的是,b“语法仅在Python 2.6中引入,所以这样做会切断早期版本的用户.

ETA:

what’s the difference?

天啊.好…

一个字节包含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,主要是基于字节的,用一种单独的方式来指定编码.因此,当您处理需要字节的组件时,必须注意将unicode字符串编码为正确的字节,而在Python 3中,您必须在以前不需要的地方明确地执行此操作.

这是一个内部实现细节,Unicode字符串在内部每单位采用“两个字节”的存储空间.你永远不会看到那个存储;你不应该以字节为单位.您正在处理的单位是概念上的角色,无论Python如何选择在内存中表示它们.

…在旁边:

这不是真的对于像Windows构建的Python的“狭窄构建”,Unicode字符串的每个单元在技术上不是字符,而是UTF-16’代码单元’.对于基本多语言平面中的字符,从0x0000-0xFFFF,您不会注意到任何差异,但是如果您使用16位范围外的字符,那么在“星体飞机”中,您会发现它们两个单位,而不是一个,再次,你分裂一个角色,当你分割他们的风险.

这是非常糟糕的,并且发生了,因为Windows(和其他人,如Java)在Unicode增长超过65,000个字符的限制之前,以UTF-16作为内存存储机制.但是,使用这些扩展字符仍然很少见,Windows上的任何人都将被使用在许多应用程序中,因此对您来说可能并不重要.

在“宽版本”中,Unicode字符串由真实字符“代码点”单元组成,因此即使BMP之外的扩展字符也可以一致且轻松地处理.付出的代价是效率:每个字符串单元在内存中占用四个字节的存储空间.

转载注明原文:准备从Python 2.x转换为3.x - 代码日志