【python】个人经验:如何写出兼容py2与py3的代码

2020-03-17 12:03:16 浏览数 (1)

问题

Python2已经停止维护,但由于历史原因,我们不得不在接下来的几年中,习惯两种语言依然共存的状况。

如果能习惯性地写出同时兼容py2与py3的代码,就可以减少很多不必要的踩坑。

前言

博主研一时用py2,研二后改用py2。

现在工作了,每次都要在本地写适配py3的代码,放到只能适配py2的服务器上去跑。对于如何写出兼容py2与py3的代码,积累了一点踩坑心得。

下文是我总结的一些个人经验。

print

这个是最明显的了。

py版本

可接受的写法

2.x

print(一条string)、print xxx、print xxx xxx

3.x

print(一条string)、print(多条string)

取交集,建议日常遵从如下写法:

代码语言:javascript复制
print( 一条string )

数值计算

  1. __future__模块的使用,可以在py2中调用py3的某些功能: from __future__ import print_function from __future__ import unicode_literals from __future__ import division from __future__ import absolute_import
  2. 除号 “/” 在py3中是精确除法;在py2中只有浮点除时才为精确除,否则为地板除。 如果想用 “精确除” ,就老老实实确保被除数或者除数是绝对的浮点型: res = float( {被除数} ) / {除数} 如果想用 “地板除” ,就老老实实用 “//”。

路径

__file__在py3下返回文件 绝对地址,在py2下则返回 相对地址

想确保在任何py版本下获取的都是绝对地址,可以借助 os.path.abspath()

代码语言:javascript复制
import os
path = os.path.abspath(__file__)

内置函数

很多常见的内置函数(又称“内建函数”,包括reduce、filter、map等等)在py2下返回的是list,在py3下返回的却是一个函数对象。

由于 list(list())效果等同于list(),而list(函数对象)可以达到和py3一样的返回效果,所以建议调用内置函数时尽量采用如下写法:

代码语言:javascript复制
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才加入的,所以建议使用如下写法:

代码语言:javascript复制
try:
	os.makedirs({文件夹名})
except:
	pass

这样同样可以达到“递归建立一个不存在的文件夹,如果存在则跳过”的效果。

其他trick

预判py版本
代码语言:javascript复制
if sys.version_info.major >= 3:		// 如果当前编译器版本是3.x
	{执行适配py3的代码}
else:
	{执行适配py2的代码} 

0 人点赞