首页 > 其他分享 >踩坑纪实:UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 21-22: invalid

踩坑纪实:UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 21-22: invalid

时间:2023-03-22 11:00:11浏览次数:43  
标签:utf 21 22 get os Popen subprocess 报错 execjs

问题出现过程

切换新的服务器之后,使用PyExecJS库报错

...
ctx = execjs.compile(js_str)
version_obj = ctx.eval('exportObj')

报错内容:

UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 21-22: invalid continuation byte

排查踩坑过程

根据报错大概可以猜测是编码解析异常,于是网上搜索+ChatGPT搜索查询原因,进行排查调试:

  1. 首先当然是“控制变量法”,原服务器是一切正常的,为什么切换新服务器就报错了呢?
    但是检查系统环境和软件环境,安装的linux版本、python版本、依赖包的版本都与旧服务器完全一致,是不是有“玄学”??

  2. 项目里的使用方式是读取js文件再用execjs解析,怀疑是不是读取文件的方式有问题,于是将原先的r方式改为rb再解码,没有任何效果;

  3. 根据报错还不知道具体是那个字符解析出错,反复换了几个js文件之后仍然没有作用,于是排除变量,排除django项目、读取文件等因素的影响,直接在python命令行对字符串解析,最终发现还是报错,但是定位到原因是中文字符无法解析;

  4. 类似的中文字符解析问题之前有遇到过,在windows上会出现UnicodeDecodeError: 'GBK' codec错误,需要修改原生的subprocess.py文件解决,或者采用如下方式,于是进行尝试,但是无效;

    # 创建一个新的 Popen 类,并继承自 subprocess.Popen
    class MySubprocessPopen(subprocess.Popen):
    	def __init__(self, *args, **kwargs):
    		# 在调用父类(即 subprocess.Popen)的构造方法时,将 encoding 参数直接置为 UTF-8 编码格式
    		super().__init__(encoding='UTF-8', *args, **kwargs)
    
    
    # 必须要在导入 PyExecJS 模块前,就将 subprocess.Popen 类重置为新的类
    subprocess.Popen = MySubprocessPopen
    

    ps: 上述代码忘了是在哪篇文章看到的了,比修改原生文件的方式好,记下来备用。

  5. 指定execjs的运行环境:

    os.environ["EXECJS_RUNTIME"] = "JScript"
    os.environ["EXECJS_RUNTIME"] = "Node"

    加上相关代码后仍然无效(其实这个才是关键,后面会讲)

  6. python3的编码问题,在py文件开头加上# -- coding: utf-8 --,或者尝试对字符串编码再解码等,都无效;

  7. 还有一系列绞尽脑汁的重装python,升级python版本等无效操作...

最终解决方案

尝试了无数方案后,复盘代码,发现可能还是运行execjs导致的问题,偶然间在一个网页上找到execjs.get().name可以获取执行环境,于是再试试:

>>> import execjs
>>> execjs.get().name
'SpiderMonkey'
>>> import os
>>> os.environ["EXECJS_RUNTIME"] = "Node"
>>> execjs.get().name
'SpiderMonkey'
>>> os.environ["EXECJS_RUNTIME"] = "JScript"
>>> execjs.get().name
'SpiderMonkey'

发现没有?在执行os.environ["EXECJS_RUNTIME"] = "xxx"前后运行环境不会有任何改变,这是什么原因呢?

再在旧服务器上执行execjs.get().name,结果得到的环境是'Node.js (V8)'

噢,因为新服务器没有使用到node环境,所以没有安装nodejs,这就是那个“变量”?

于是在新服务器上安装同版本nodejs,执行成功,大功告成!

标签:utf,21,22,get,os,Popen,subprocess,报错,execjs
From: https://www.cnblogs.com/JeromeLong/p/17242883.html

相关文章

  • AutoCloseLockNote 2023年3月22日
    AutoCloseLockNote2023年3月22日 REM我的腾讯QQ电子邮箱地址是[email protected]说明:我把SynologyDiskStationDS3622xs+群晖NAS网络附属存储服务器的管理......
  • 软件工程3月21日结队日报
    学习时间:五小时代码量:800博客量:1任务:今天对地铁查询系统PC端的前端页面进行了一些css与js的美化,并且完成了安卓端的查询线路、查询站点的功能,对于起点---终点查询也完成......
  • 3月21日
    AndroidStudio提供了更加高级的布局文件编辑器,(1)我们在编写XML文件的时候,能实时查看布局文件。(2)能直接以拖控件的方式编辑布局文件。当然这些Eclipse也有。   只有这......
  • 2023.3.21晚报
    1.英语元音发音2.算法:红蓝白三色球排序(题目就不写了,leetcode上有)解法思路:对0,1生成两个指针,遍历数组,当数组数目不为指针所指向数字时向后遍历,与指向数字相等时则与当前指......
  • 3/21人月神话读书笔记
    作为开章第一篇,就先来说说为什么“人月”是“神话”。小学的时候我们都做过这样的应用题:“工厂需要加工一批零件,安排5名工人的话需要10小时完成,那么安排25名工人加工,多少......
  • 每日总结2023/3/21
    今天进行了Android的地铁查询操作,主要是进行了简单的前两步,线路和站点查询,并为Android安装了搜狗输入法,以保障汉字的输入。代码行大概50 优化更改textview使之高度变......
  • 3.21博客
    总结:1.完成python的pta练习主要问题:6-2计算时一直报错非零返回本题要求计算输入两个正整数x,y(x<=y,包括x,y)素数和。函数isPrime用以判断一个数是否素数,primeSum函数返......
  • day21 (2023.3.21)
    1.迭代List接口类型容器 运行结果: 2.迭代Set接口类型容器 运行结果: 3.迭代Map接口类型容器 运行结果: 4.在迭代器中删除元素: 运行结果: 5.操......
  • 每日总结 3.21
    今天进行了Android的地铁查询操作,主要是进行了简单的前两步,线路和站点查询,并为Android安装了搜狗输入法,以保障汉字的输入。代码行大概50 优化更改textview使之高度变......
  • 2023/3/21
    今天最大的进度,就是配置好安卓的PDF的开源库。之前找了很长时间的开源库,但是往往就是配置依赖的时候死掉。不仅仅需要在build.gradle里面导入依赖。而且还需要在setting.gr......