编写同时兼容Python2.x与Python3.x版本的代码的几个示例_python

编写兼容Python2.x与3.x代码

当我们正处于Python 2.x到Python 3.x的过渡期时,你可能想过是否可以在不修改任何代码的前提下能同时运行在Python 2和3中。这看起来还真是一个合理的诉求,但如何开始呢?哪些Python 2 代码在 3.x 解释器执行时容易出状况呢?
print vs print()

如果你想的和我一样,你或许会说print语句,这是个很好的着手点,先简单展示一下,print在2.x中是一条语句,而在3.x中它是一个关键字或者是保留字。换句话说,因为这个变化涉及到语言的语法,你不可以使用在if语句中,Python仍然没有#ifdef 宏。下面尝试把括号里面的参数打印出来:

>>> print('Hello World!')
Hello World!

很酷,这个在Python2和Python3中都可以运行,而且运行的效果是一样的,再来看看下面这段:
 

>>> print(10, 20) # Python 2
(10, 20)

此时,你并没有像前面那样幸运得到一样的结果,Python2中打印的是元组(tuple),而在Python3中传递多个参数到print()里面时打印的是两个值:
 

>>> print(10, 20) # Python 3
10 20

如果你思考得比较多的话,我们可以检查print是否是一个关键字,keyword模块包含一个关键字列表。print在3.x中不是关键字,可以简单验证一下:
 

>>> import keyword
>>> 'print' in keyword.kwlist
False

作为一名聪明的程序员,你可能在2.x中尝试的时候期待的结果是True,尽管这并没有错,但是为了达到Python3的效果,但你仍然会因为其他原因导致失败。
 

>>> import keyword
>>> if 'print' in keyword.kwlist:
...  from __future__ import print_function
...
File "", line 2
SyntaxError: from __future__ imports must occur at the beginning of the file

一种解决方案是使用一个函数,其功能类似于print,其中之一是sys.stdout.write(),另一个是distutils.log.warn()。不管出于什么原因,我们决定使用后者。“hello world”的例子看起来是这样的:
 

# Python 2.x
print 'Hello World!'
# Python 3.x
print('Hello World!')

下面的代码就可以在两个版本中通用:
 

# Python 2.x & 3.x compatible
from distutils.log import warn as printf
printf('Hello World!')

为什么我们不用sys.stdout.write()呢,因为我们需要添加一个NEWLINE字符在字符串的结尾来兼容这种行为(python2.x中write方法不会换行):
 

# Python 2.x & 3.x compatible
import sys
sys.stdout.write('Hello World!n')

Import your way to a solution

一般情况情况下,import时没什么烦恼,只要正确的导入就行,但在下面代码中,我们想导入urlopen()函数,在Python2中,他同时存在与urllib2和urllib2中(我们使用后者),在Python3中,他被集成到了urllib.request中,而你的方案是要既能在2.x和3.x中正常工作:

try:
 from urllib2 import urlopen
except ImportError:
 from urllib.request import urlopen

出于对内存的保护,也许你对iterator(Python3)版本的zip()更加有兴趣,在Python2中,iterator版本是itertools.izip()。这个函数在Python3中被重命名替换成了zip()。如果你使用迭代版本,导入语句也非常直白:
 

try:
 from itertools import izip as zip
except ImportError:
 pass

另一个列子是看来来并不怎么优雅的StringIO类,在Python2中,纯Python版本是StringIO模块,意味着访问的时候是通过StringIO.StringIO,同样还有一个更为快速的C语言版本,位于cStringIO.StringIO,不过这取决你的Python安装版本,你可以优先使用cStringIO然后是StringIO(如果cStringIO不能用的话)。在Python3中,Unicode是默认的string类型,但是如果你做任何和网络相关的操作,很有可能你不得不用ASCII/字节字符串来操作,所以代替StringIO,你要io.BytesIO,为了达到你想要的,这个导入看起来有点丑:
 

try:
 from io import BytesIO as StringIO
except ImportError:
 try:
  from cStringIO import StringIO
 except ImportError:
  from StringIO import StringIO

Putting it all together

如果你运气好的话,上面那些就是你要准备做的全部,剩下的代码都比开始设置的地方更简单。如果你按照上面的方式导入了distutils.log.warn()[printf()],url*urlopen(),*.StringIO和一个标准的导入:xml.etree.ElementTree(2.5及更新的),现在你就可以写一个非常简短短的解析器来展示从Google News服务中提供的头条故事(译注:当然首先得备一个梯子),只需八行代码:
 

g = urlopen('http://news.google.com/news?topic=h&output=rss')
f = StringIO(g.read())
g.close()
tree = xml.etree.ElementTree.parse(f)
f.close()
for elmt in tree.getiterator():
 if elmt.tag == 'title' and not
   elmt.text.startswith('Top Stories'):
  printf('- %s' % elmt.text)

这段脚本在2.x和3.x下面运行时,不需要做任何改动,运行效果完全一样,当然,如果你正在使用的是2.4或者更老的版本,你需要单独下载ElementTree。

但是有时候感觉这些改变把你优雅的Python代码弄得一团糟,毕竟可读性才是最重要的,如果你要优先保证代码的整洁而且在不修改任何地方的前提下运行在两个版本的Python环境中,那么你可以看一下six包。

six一个兼容库,它的主要任务是提供接口隐藏复杂的细节,你可以在这里找到它。无论你是使用像six这样的库还是用自己的方法来做,我们希望这个简短的介绍可以让你开始考虑写的代码能够在2.x和3.x下同时运行。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索python
兼容
企业文化 编写示例、python代码示例、python示例程序、python 示例、python入门代码示例,以便于您获取更多的相关知识。

时间: 2024-12-17 11:18:37

编写同时兼容Python2.x与Python3.x版本的代码的几个示例_python的相关文章

Python3.x版本中新的字符串格式化方法_python

我们知道Python3.x引入了新的字符串格式化语法.不同于Python2.x的 复制代码 代码如下: "%s %s "%(a,b)  Python3.x是 复制代码 代码如下: "{0} {1}".format(a,b)  今天我在用MySQLdb时,需要用带参数的 复制代码 代码如下: cursor.execute(sql,param)  语句来完成SQL操作.被其他文章的陈旧说法给误导,用了 复制代码 代码如下: cursor.execute('insert

python3.3使用tkinter开发猜数字游戏示例_python

利用这个小游戏可以学习一下ython3.3中tkinter的使用方法 复制代码 代码如下: # -*- coding: utf-8 -*-import tkinter as tkimport sysimport randomimport re number = random.randint(0,1024)running = Truenum = 0nmaxn = 1024nminn = 0 def eBtnClose(event):    root.destroy() def eBtnGuess(

让python同时兼容python2和python3的8个技巧分享_python

python邮件列表里有人发表言论说"python3在10内都无法普及".在我看来这样的观点有些过于悲观,python3和python2虽然不兼容,但他们之间差别并没很多人想像的那么大.你只需要对自己的代码稍微做些修改就可以很好的同时支持python2和python3的.下面我将简要的介绍一下如何让自己的python代码如何同时支持python2和python3. 一.放弃python 2.6之前的python版本 python 2.6之前的python版本缺少一些新特性,会给你的迁移

Mac OS X10.9安装的Python2.7升级Python3.3步骤详解_python

第1步:官网下载Python3.3 这里面有windows和mac os x下的安装程序,下载那个64位的安装程序 第2步:安装下载的img文件,安装完后的目录如下: 复制代码 代码如下: /Library/Frameworks/Python.framework/Versions/3.3 第3步:移动python的安装目录 原来的安装目录见第2步,不过所有的python都在/System/Library/Frameworks/Python.framework/Versions目录中,所以最好使用

Bootstrap编写一个兼容主流浏览器的受众门户式风格页面_javascript技巧

上一次写的<Bootstrap编写一个兼容主流浏览器的受众巨幕式风格页面>(点击打开链接)部分老一辈的需求可能对这种后现代的风格并不满意,没关系,我们完全可以改变布局拉成门户式的风格,他们马上就接受了:  首先,门户式的布局的大概你要清楚,这一才利于我们快速布局开头是一个较小的巨幕,后是一个导航栏,这里还是用到了按钮组接着是各个专栏,这里是关于bootstrap栅格系统与面板的运用,最后是版权信息,这里还是一个面板. 反正个人觉得这种门户式的布局风格烂大街,但不知道为何似乎很受众的样子. 我们

selenium+python自动化81-html报告优化(饼图+失败重跑+兼容python2&amp;3)

优化html报告 为了满足小伙伴的各种变态需求,为了装逼提升逼格,为了让报告更加高大上,测试报告做了以下优化: 测试报告中文显示,优化一些断言失败正文乱码问题 新增错误和失败截图,展示到html报告里 优化点击截图放大不清晰问题 增加饼图统计 失败后重试功能 兼容python2.x 和3.x 报告效果 1.生成的测试报告效果如下图,默认展示报错和异常的用例,失败重试的用例结果也会统计进去. 2.点击显示截图,可以直接显示截取的图片,无需保存到本地 table表格 1.修改表格的td后面内容,可以

使用GCC和GNU Binutils编写能在x86实模式运行的16位代码

使用GCC和GNU Binutils编写能在x86实模式运行的16位代码 不可否认,这次的标题有点长.之所以把标题写得这么详细,主要是为了搜索引擎能够准确地把确实需要了解GCC生成16位实模式代码方法的朋友带到我的博客.先说一下背景,编写能在x86实模式下运行的16位代码,这个话题确实有点复古,所以能找到的资料也相应较少.要运行x86实模式的程序,目 前我知道的只有两种方式,一种是使用DOS系统,另一种是把它写成引导扇区的代码,在系统启动时直接运行.很显然,许多讲自己实现操作系统的书籍都会讲到

c语言-求用C语言编写将“hello”这样的字符串转化为十六进制的代码实现

问题描述 求用C语言编写将"hello"这样的字符串转化为十六进制的代码实现 求用C语言编写将"hello"这样的字符串转化为十六进制的代码实现,急急急!!! 解决方案 #include<stdio.h> void main() { char str[]="abhello"; char *p=str; while(*p) { printf("%x ",*p++); } } 解决方案二: #include "

播放视频-用java三大框架编写视频上传并能点击播放的代码

问题描述 用java三大框架编写视频上传并能点击播放的代码 本人新手,用java实现视频的上传并且能点击播放的功能,求详细一点的代码 解决方案 直接用百度的Ueditor插件得了..或者就是上传视频功能,然后前台找个播放器