玩命加载中 . . .

python 读取yaml文件抛UnicodeDecodeError异常


概述

读取yaml配置文件,在Linux上运行OK,但相同代码在Windows上运行报错:

ImportError while loading conftest 'D:\workspace\API\conftest.py'.
conftest.py:6: in <module>
    from utils.config import CONFIG
utils\config.py:16: in <module>
    CONFIG=read_config()
utils\config.py:13: in read_config
    config = yaml.safe_load(file)
C:\Users\Wang\AppData\Local\Programs\Python\Python311\Lib\site-packages\yaml\__init__.py:125: in safe_load
    return load(stream, SafeLoader)
C:\Users\Wang\AppData\Local\Programs\Python\Python311\Lib\site-packages\yaml\__init__.py:79: in load
    loader = Loader(stream)
C:\Users\Wang\AppData\Local\Programs\Python\Python311\Lib\site-packages\yaml\loader.py:34: in __init__
    Reader.__init__(self, stream)
C:\Users\Wang\AppData\Local\Programs\Python\Python311\Lib\site-packages\yaml\reader.py:85: in __init__
    self.determine_encoding()
C:\Users\Wang\AppData\Local\Programs\Python\Python311\Lib\site-packages\yaml\reader.py:124: in determine_encoding
    self.update_raw()
C:\Users\Wang\AppData\Local\Programs\Python\Python311\Lib\site-packages\yaml\reader.py:178: in update_raw
    data = self.stream.read(size)
E   UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 208: illegal multibyte sequence

解决过程

源码内容参考如下:

root@Gavin:~/automation/API/utils# cat config.py 
import os
import yaml

def get_config_path():
    # 根据项目结构返回config.yaml的路径。假定此文件位于与configs目录平行的utils目录中
    base_dir = os.path.dirname(os.path.dirname(__file__))
    return os.path.join(base_dir, 'configs', 'config.yaml')

def read_config():
    # 读取配置文件并返回配置数据
    config_path = get_config_path()
    with open(config_path, 'r') as file:
        config = yaml.safe_load(file)
    return config

CONFIG=read_config()
root@Gavin:~/automation/API/utils# 

Linux下运行正常,Windows运行抛如上所示的异常。

解决方法是:

修改rb模式读取指定文件,即修改 with open(config_path, 'r') as file:with open(config_path, 'rb') as file:

参考如下:

root@Gavin:~/automation/API/utils# cat config.py 
import os
import yaml

def get_config_path():
    # 根据项目结构返回config.yaml的路径。假定此文件位于与configs目录平行的utils目录中
    base_dir = os.path.dirname(os.path.dirname(__file__))
    return os.path.join(base_dir, 'configs', 'config.yaml')

def read_config():
    # 读取配置文件并返回配置数据
    config_path = get_config_path()
    with open(config_path, 'rb') as file:
        config = yaml.safe_load(file)
    return config

CONFIG=read_config()
root@Gavin:~/automation/API/utils# 

说明

默认情况下,Python 在不同操作系统上可能会使用不同的文件编码。例如,Linux 通常使用 UTF-8,而 Windows 通常使用 GBK 或其他编码。

在最初的代码中,使用 r 模式打开文件可能会导致在 Windows 上发生 UnicodeDecodeError,因为文件内容可能并不是以 Windows 默认的编码(例如 GBK)存储的。为了避免这个问题,你需要明确指定文件打开时使用的编码。

除了上面的修改方法外,也可以指定编码:

修改 with open(config_path, 'r') as file:with open(config_path, 'r', encoding='utf-8') as file: 可以更明确地指定文件的编码。

另外:

使用 rb(以二进制模式读取文件)可以避免编码问题,因为此模式下,文件内容不会被解码。但是,文件内容作为二进制数据传递给 yaml.safe_load 并不是一个好办法,因为 yaml.safe_load 期望的是字符数据而非字节数据。


文章作者: Gavin Wang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Gavin Wang !
  目录