问题
Python2已经停止维护,但由于历史原因,我们不得不在接下来的几年中,习惯两种语言依然共存的状况。
如果能习惯性地写出同时兼容py2与py3的代码,就可以减少很多不必要的踩坑。
前言
博主研一时用py2,研二后改用py2。
现在工作了,每次都要在本地写适配py3的代码,放到只能适配py2的服务器上去跑。对于如何写出兼容py2与py3的代码,积累了一点踩坑心得。
下文是我总结的一些个人经验。
这个是最明显的了。
py版本 | 可接受的写法 |
---|---|
2.x | print(一条string)、print xxx、print xxx xxx |
3.x | print(一条string)、print(多条string) |
取交集,建议日常遵从如下写法:
代码语言:javascript复制print( 一条string )
数值计算
__future__
模块的使用,可以在py2中调用py3的某些功能: from __future__ import print_function from __future__ import unicode_literals from __future__ import division from __future__ import absolute_import- 除号
“
/
” 在py3中是精确除法;在py2中只有浮点除时才为精确除,否则为地板除。 如果想用 “精确除” ,就老老实实确保被除数或者除数是绝对的浮点型: res = float( {被除数} ) / {除数} 如果想用 “地板除” ,就老老实实用 “//
”。
路径
__file__
在py3下返回文件 绝对地址,在py2下则返回 相对地址 。
想确保在任何py版本下获取的都是绝对地址,可以借助 os.path.abspath()
:
import os
path = os.path.abspath(__file__)
内置函数
很多常见的内置函数(又称“内建函数”,包括reduce、filter、map等等)在py2下返回的是list,在py3下返回的却是一个函数对象。
由于 list(list())
效果等同于list()
,而list(函数对象)
可以达到和py3一样的返回效果,所以建议调用内置函数时尽量采用如下写法:
res = list( 内置函数的调用 )
另外,reduce()函数已被py3从全局名字空间里移除了,所以能别用reduce尽量别用,或者用其他函数替换之也可。
导入自定义库文件
py2默认是按照 相对路径 导入模块和包,然而py3却默认按照 绝对路径 导入。
- 文件路径直接在当前工作目录下时:py2和py3都可以通过如下方式来导入相同目录下的库文件:import util
- 文件路径不直接在当前工作目录下时:py3导入相同目录下的库文件就不能再那么写了,而是要改一下:if sys.version_info.major >= 3 and os.path.dirname(os.path.abspath(__file__)) != os.getcwd(): from . import util else: import util
一些常见的api
os
用于创建递归目录树的 os.makedirs({文件夹名}, exist_ok=True)
中,exist_ok
参数是py3.2才加入的,所以建议使用如下写法:
try:
os.makedirs({文件夹名})
except:
pass
这样同样可以达到“递归建立一个不存在的文件夹,如果存在则跳过”的效果。
其他trick
预判py版本
代码语言:javascript复制if sys.version_info.major >= 3: // 如果当前编译器版本是3.x
{执行适配py3的代码}
else:
{执行适配py2的代码}