Python 3to2 踩坑记录

2023年 10月 11日 50.2k 0

Python2和Python3在语法和模块的使用上会有一些差别。目前通常使用Python3编写脚本,实际工作中有很多运维或者测试脚本还在使用Python2运行。这时可以使用python包3to2将Python3脚本直接转为Python2脚本。
但3to2有时并不那么智能,它对于Python2~Python3之间发生变更的语法比较有效,但对于部分Python3新引入的特性,并不能很好的转化。以下记录了工作中踩过的一些坑,仅供参考。

1. init.py文件

在Python 3.2及之前的版本中,如果要将一个目录声明为包,需要在该目录中创建一个空的__init__.py文件。Python 3.3+版本以后,Python3具有隐式命名空间包,允许它创建不带__init__.py文件的包。如果你是在python3.3以上的版本编写代码,并且没有创建__init__.py文件。那么在使用3to2转换代码后,需要手动在package文件夹下创建__init__.py文件。如下目录:

package/
    __init__.py
    module

可以像这样导入包和模块:

import package.module

如果是将开源的第三方库打包放入代码中,更推荐下面这种导入方式。这种方式会将package文件夹加入模块的搜索路径,同时也会搜索系统默认路径。

sys.path.append("package")
import module

2. ping3库

ping3是一个用于执行ping命令的Python库。当你的python脚本需要同时兼容windows和linux时,ping指令会有所不同,使用ping3库可以保证跨平台的兼容性。但是,ping3库只支持python3.x。如果你要在python2.x环境中使用ping,可以自己封装一个ping函数

import os
import platform
import subprocess

def ping(host)
    param = "-n" if platform.system().lower() == "windows" else "-c"
    command = ["ping", param, "1", host]
    devnull = open(os.devnull, "w")
    res = subprocess.call(command, stdout=subprocess.PIPE, stderr=devnull) == 0
    devnull.close()
    return res

使用platform模块判断当前平台为windows还是linux。将输出重定向到os模块的devnull,能保证windows/linux平台兼容性。

3. 线程池/多线程

python中线程池的使用可以简化线程管理。但要注意,ThreadPoolExecutor (线程池)是在python3.2版本引入的,如果你需要使用3to2使你的脚本在python2.x中运行,那么不要使用ThreadPoolExecutor,老老实实使用threading模块管理你的线程。

4. 生成有序列表

我在python3中编写了以下语句,用来生成一个0 ~ n-1的有序列表

my_list=list(range(0, n))

当使用3to2后,它变成了

my_list=xrange(0, n)

这样生成的my_list并不是一个list对象,导致后续调用报错。目前原因不明。

5. 有序字典

在python3.5及以前,字典是不能保证顺序的。python3.6已经使字典变得有序。如果你需要保证字典的顺序,可以使用collections.OrderedDict来创建有序字典。

dict = {"a": "A", "b": "B"}
print(dict)
import collections

order_dict = collections.OrderedDict()
order_dict["a"] = "A"
order_dict["b"] = "B"
print(order_dict)

6. 写入文件报错

我在python3中写了如下代码,用于将数据写入到csv文件中。

with open("data.csv", "w", newline="") as file:
    writer = csv.writer(file)
    writer.writerow(my_list)

当使用3to2转换后,出现如下报错:

# TypeError: write() argument 1 must be unicode, not str

需要在打开文件时指定编码格式:

import codecs

with codecs.open("data.csv", "w", "utf-8")as file:
    writer = csv.writer(file)
    writer.writerow(my_list)

相关文章

服务器端口转发,带你了解服务器端口转发
服务器开放端口,服务器开放端口的步骤
产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
如何使用 WinGet 下载 Microsoft Store 应用
百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

发布评论