Python3 UnicodeEncodeError: 'ascii' codec 错误处理

情况描述

我司现在使用Airflow,搭建在Python3环境上,奇怪的是,在代码里不能出现中文,print\logging的时候,如果有中文,就报错:

UnicodeEncodeError: 'ascii' codec can't encode character u'***' in position ***: ordinal not in range(128) 

我的疑问有二:

  1. Python3不是原生支持utf-8的吗?
  2. 为什么本地ubuntu可以,docker不可以?(我用的是ubuntu18.04镜像,安装Python3.6)

经多方查询,发现在docker镜像中,由于locale的设置问题,导致Python3并没有使用utf-8作为sysout编码。

关于什么是locale,可以查看ubuntu的官方文档https://wiki.ubuntu.org.cn/Locale,简而言之,它定义了系统里文字使用何种方式编码。默认的ubuntu:18.04镜像的locale是POSIX,这种设置会默认使用ascii编码,从而导致上面的错误。

如何判断你遇到了locale问题

在环境中输入:

$ python -c "import sys; print(sys.stdout.encoding)"
UTF-8

如果你的返回值不是UTF-8,那么你很有可能会遇到unicode输入问题

注意,以下代码返回UTF-8并不能说明没有问题

python -c "import sys; print(sys.getdefaultencoding())"

解决办法

设置docker中的环境变量,使Python可以使用正确的编码方式

操作1:设置PYTHONIOENCODING

在Dockerfile中添加:

ENV PYTHONIOENCODING=UTF-8

据说此方法可以解决问题,但是我没有成功,locale问题依然存在,有兴趣的同学可以试一下。

操作2:设置locale

在Dockerfile中添加:

RUN apt-get update
RUN apt-get install -y locales
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && \
    locale-gen
ENV LC_ALL en_US.UTF-8 
ENV LANG en_US.UTF-8  
ENV LANGUAGE en_US:en     

设置完成

操作3:使用Python3.7!

这可能是最简单的办法了,Python3.7中,PEP-538说明,默认将Python的locale从CPOSIX改为默认为UTF-8.
详见 https://docs.python.org/3.7/whatsnew/3.7.html#whatsnew37-pep538

所以如果你没有强依赖的话,可以考虑换3.7的镜像。

参考资料

  • https://leimao.github.io/blog/Docker-Locale/

你可能感兴趣的:(编程思考,python)