PyExecJs 运行含有中文的JavaScript文件时,出现编码错误的解决方案

问题分析

​ 在 Python 中使用 PyExecJS 库运行 JavaScript 代码文件时,若文件中含有中文字符,则会被抛出一个文件编码异常 UnicodeEncodeError: 'gbk' codec can't encode character '\ufeff' in position 61: illegal multibyte sequence

异常详情如下:

Traceback (most recent call last):
  File "D:/Projects/PythonProjects/ConfigurationTableVerificationTools/checkoutAllRoomFishCanKill.py", line 233, in <module>
    game_table = execjs.get('local_node').compile(js_code).eval('_default')
  File "D:\Projects\PythonProjects\ConfigurationTableVerificationTools\venv\lib\site-packages\execjs\_abstract_runtime_context.py", line 27, in eval
    return self._eval(source)
  File "D:\Projects\PythonProjects\ConfigurationTableVerificationTools\venv\lib\site-packages\execjs\_external_runtime.py", line 77, in _eval
    return self.exec_(code)
  File "D:\Projects\PythonProjects\ConfigurationTableVerificationTools\venv\lib\site-packages\execjs\_abstract_runtime_context.py", line 18, in exec_
    return self._exec_(source)
  File "D:\Projects\PythonProjects\ConfigurationTableVerificationTools\venv\lib\site-packages\execjs\_external_runtime.py", line 86, in _exec_
    output = self._exec_with_pipe(source)
  File "D:\Projects\PythonProjects\ConfigurationTableVerificationTools\venv\lib\site-packages\execjs\_external_runtime.py", line 102, in _exec_with_pipe
    stdoutdata, stderrdata = p.communicate(input=input)
  File "C:\Program Files\Python38\lib\subprocess.py", line 1028, in communicate
    stdout, stderr = self._communicate(input, endtime, timeout)
  File "C:\Program Files\Python38\lib\subprocess.py", line 1393, in _communicate
    self._stdin_write(input)
  File "C:\Program Files\Python38\lib\subprocess.py", line 962, in _stdin_write
    self.stdin.write(input)
UnicodeEncodeError: 'gbk' codec can't encode character '\ufeff' in position 61: illegal multibyte sequence

解决方案

​ 网络上其他文章的解决方案大多是直接修改 Python 标准库中 subprocess.py 模块中代码的方式,将其中编码格式设定为 UTF-8

​ 但我认为,不到万不得已,能够在不修改官方标准模块文件,不对非项目代码文件进行侵入式的修改,就能够将问题解决的解决方案,才是更值得推荐的做法。

​ 通过尝试,发现借助 Python 高度动态化的特性,在代码运行过程中,对 subprocess.py 模块中的 Popen 类进行重置及可解决该问题。具体代码如下。

import subprocess

# 创建一个新的 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

# 导入 PyExecJS 模块
import execjs

# 在后面继续写程序具体的执行逻辑 ...
  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值