项目从pyhon2.7升级到python3.9
一、看项目引用了哪些开源模块#####
我们项目我捋了一遍用了三个开源:
- pyzmq
- pyserial
- gdb
前两个直接在源码中(随便哪个入口文件头部一般会注释开源信息),找到对应的github地址,我是先自己在电脑上用pip3安装的(命令 pip3 install pyzmq/pyserial),安装完了后, 在路径
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/serial
/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/zmq
找到这两个文件夹,然后拷贝到项目,就搞定了。
第三个gdb,没用到python,只是借用了它batch功能,所以不用升级,兼容python3.
开源模块升级完后,记得从原有项目中提出来,开始对剩下的文件进行第二步动作。
二、采用2to3工具
参考这篇文章,讲的很详细
2to3 - 自动将 Python 2 代码转为 Python 3 代码
就在终端使用命令
2to3 --output-dir=python3-version/mycode -W -n python2-version/mycode
我使用该命令是这样的
2to3 --output-dir=ph1_Script_Python3.0/ -w -n ph1_Script_Python3.0/
这样转换出来的包总是报 ImportError: attempted relative import with no known parent package的问题,这是因为2to3工具将项目import默认转成了相对地址,所以我增加了一个参数 -f all -x import ,让2to3不要把项目的import转成相对路径,修改后命令如下
2to3 -f all -x import --output-dir=ph1_Script_Python3.0/ -w -n ph1_Script_Python3.0/
这样转换出来就没有impor的问题了,然后对项目不是特别熟,所以将可选的修复器全部都选上了,最后执行的命令是这样的
2to3 -f all -x import -f buffer -f idioms -f set_literal -f ws_comma --output-dir=ph1_Script_Python3.0/ -w -n ph1_Script_Python3.0/
三、微调
前两个步骤将项目已经完全升级成python3.0版本了,接下来就是看build的时候会出什么问题,针对性的解决,就我项目而言,出现了以下几个问题
- .encode('string-escape' )
python2
addLog("diag:{}".format(totalRes.encode('string-escape')))
python3
# addLog("diag:{}".format(totalRes.encode('latin1').decode('unicode-escape').encode('latin1')))
- exception.message
Python2.7
try:
main()
except Exception as ex:
ex.message = "Software error-" + str(ex)
OutputExceptAndExit(ex)
...
output = ex.message
Python3.9
try:
main()
except Exception as ex:
ex.args = ex.args+("Software error-" + str(ex),)
OutputExceptAndExit(ex)
...
output = repr(ex)
python2的try exception和python3的区别如下
image.png
- python2 subprocess 函数返回值都是string
python2
p1 = Popen(helloGDB, stdin = PIPE, stdout = PIPE, stderr = PIPE, shell = True)
python3
p1 = Popen(helloGDB, stdin = PIPE, stdout = PIPE, stderr = PIPE, shell = True, universal_newlines=True)
python3 subprocess的返回值默认都是bytes,所以在创建subprocess对象的时候传入参数universal_newlines=True,让返回值都为string,从而改动比较小
- python3的pyserial函数传入的参数都要求是bytes
python2
self.port.write(cmd)
res = self.port.read_until(terminator)
python3
self.port.write(cmd.encode())
res_bytes = self.port.read_until(terminator)
res = str(res_bytes, encoding="utf-8")