Docker容器运行Python读取UTF-8文件报UnicodeEncodeError解决方法
问题描述
编写的Python文件读取代码如下:
with open("/media/file.txt", 'r', encoding='utf-8') as file: content = file.read()
上述代码在本地IDE、本机CMD环境中均可正常执行,目标读取的文件包含UTF-8编码字符。但在自行构建的Docker镜像中运行该代码时抛出异常,该镜像基于Ubuntu 18.04,搭载Python 3.6及以上版本,镜像构建配置如下:
RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ build-essential \ zlib1g-dev \ glade \ python3-dev \ python3-pip \ python3-setuptools \ pkg-config \ libglib2.0-dev \ libgirepository1.0-dev \ libcairo2-dev \ gir1.2-gtk-3.0 \ && rm -rf /var/lib/apt/lists/* RUN pip3 install wheel RUN pip3 install pycairo RUN pip3 install PyGObject RUN pip3 install requests RUN pip3 install pyinstaller
运行时抛出的具体错误信息为:
'ascii' codec can't encode character '\xfc' in position 63: ordinal not in range(128)
问题根因
报错核心原因是Docker容器默认使用POSIX/C区域配置,默认编码为ASCII。虽然open函数已经指定使用UTF-8读取文件,但读取到非ASCII内容后,后续涉及标准输出打印、GTK组件(镜像中安装了PyGObject、GTK3.0)文本渲染、PyInstaller打包逻辑执行时,会自动调用系统默认编码处理字符串,遇到ASCII编码范围外的字符(本次报错的\xfc对应字符ü)就会抛出编码异常。本地环境默认locale一般为UTF-8格式,因此不会触发该问题。
解决步骤
- 首先进入运行中的容器执行
locale命令验证,可看到返回结果中LANG=C、LC_ALL=C,所有编码配置均为POSIX标准,确认是locale配置缺失导致的问题。 - 修改Dockerfile的apt安装逻辑,新增locales包安装并生成UTF-8编码配置,修改后的apt安装段如下:
RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ build-essential \ zlib1g-dev \ glade \ python3-dev \ python3-pip \ python3-setuptools \ pkg-config \ libglib2.0-dev \ libgirepository1.0-dev \ libcairo2-dev \ gir1.2-gtk-3.0 \ locales \ && locale-gen en_US.UTF-8 \ && update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 \ && rm -rf /var/lib/apt/lists/*
- 在Dockerfile中新增全局环境变量,强制系统和Python进程使用UTF-8编码,配置加在apt安装段之后即可:
ENV LANG=en_US.UTF-8 \ LANGUAGE=en_US:en \ LC_ALL=en_US.UTF-8 \ PYTHONIOENCODING=utf-8
其中PYTHONIOENCODING=utf-8会强制Python进程的标准输入、输出、错误流使用UTF-8编码,避免Python层面忽略系统配置回退到ASCII编码。
- 如果使用PyInstaller打包后运行程序仍有报错,可在Python代码的最开头加入以下配置,强制重设标准流编码:
import sys sys.stdout.reconfigure(encoding='utf-8') sys.stderr.reconfigure(encoding='utf-8')
注意:原有open函数指定encoding='utf-8'的写法是正确的,不需要修改,问题并非出在文件读取环节。
内容的提问来源于stack exchange,提问作者Azii
相关产品推荐
相关产品推荐

