Python3.6 sys.stdout.encoding的输出为'ANSI_X3.4-1968'

故事的起始是这样的:
在ubuntu 16.04服务器上使用python3.6.8的conda环境,配置jupyter notebook服务器,jupyter notebook --generate-config后,提示错误:

UnicodeEncodeError: 'ascii' codec can't encode characters in position 1279-1280: ordinal not in range(128)

啥,怎么可能是acsii编码,linux不都是默认utf8编码的么?带着怀疑的心态,开始谷歌。

然后按照网上的提示,开始测试我的python3.6.8:

>>> import sys
>>> sys.stdout.encoding
'ANSI_X3.4-1968'
>>>

其中,ANSI_X3.4-1968就是一种ASCII1,也就是说,此时我的python环境的默认输出编码方式为ASCII,所以才会出现最上面配置jupyter服务器的错误。

但当我换用另外一个基于python3.7的conda环境时,python环境的默认输出编码方式却是UTF-8!查阅官方文档后发现,python3.7貌似会强制使用UTF-8的运行时模式2
Python3.6 sys.stdout.encoding的输出为'ANSI_X3.4-1968'_第1张图片
但我并不想使用python3.7的环境,依然想找到设置python3.6编码方式为utf8的方法。尝试若干解决方案之后,发现在~./bash_profile中添加环境变量可以解决这个问题3

export PYTHONIOENCODING=utf-8

从名字中看好像就是设置python的io编码为utf8。这样设置之后,python3.6环境的默认输出编码方式正确变为了utf8。

但我仍然想要知道,为什么我所知道的linux服务器都是utf8编码的,而我的python3.6.8的conda环境却这么有主见,选择ascii编码呢?

查阅相关资料后发现,linux下有locale命令能够打印出当前的语言环境变量,于是我进行了尝试,输出如下。

locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
LANG=zh_CN.UTF-8
LANGUAGE=
LC_CTYPE="zh_CN.UTF-8"
LC_NUMERIC="zh_CN.UTF-8"
LC_TIME="zh_CN.UTF-8"
LC_COLLATE="zh_CN.UTF-8"
LC_MONETARY="zh_CN.UTF-8"
LC_MESSAGES="zh_CN.UTF-8"
LC_PAPER="zh_CN.UTF-8"
LC_NAME="zh_CN.UTF-8"
LC_ADDRESS="zh_CN.UTF-8"
LC_TELEPHONE="zh_CN.UTF-8"
LC_MEASUREMENT="zh_CN.UTF-8"
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=

乍一看,感觉十分正常。除了有些变量等号右边为空,其他环境变量都设置成了"zh_CN.UTF-8",也应该就是utf8格式。看到网上很多说要在系统环境配置文件比如说/etc/profile中加入LC_ALL="zh_CN.UTF-8"之类的方法,我试都不想试。一是因为这里最基本的环境变量LANG已经等于zh_CN.UTF-8了,我觉得问题不会出在环境变量没有设置为utf8上,二是因为我不是很想随便动系统环境。

在ubuntu的官网上,我找到了查看服务器操作系统可用语言环境的指令4

locale -a

在我的服务器上输出:

(jt_py36) jiangtanzju@93b58edb-aae4-402d-b292-97e31978b7d4:~$ locale -a
C
C.UTF-8
POSIX

马上联想到上面locale的输出,其中的zh_CN.UTF-8在这儿并不能看见,也就是说这个环境在我的服务器上并不能使用!再联想到locale输出中的报错locale: Cannot set LC_ALL to default locale: No such file or directory,我基本能确定是系统语言环境缺失的问题了。将locale: Cannot set LC_ALL to default locale: No such file or directory扔入谷歌中查询,看到了许许多多千奇百怪的方法,找了最简单的一个方法尝试5

sudo apt-get -y install language-pack-zh-hans

在bash中执行这条指令之后,再次执行locale -a,输出如下:

(jt_py36) jiangtanzju@93b58edb-aae4-402d-b292-97e31978b7d4:~$ locale -a
C
C.UTF-8
POSIX
zh_CN.utf8
zh_SG.utf8

然后删除掉上方可行的一个python环境变量export PYTHONIOENCODING=utf-8,测试sys.stdout.encoding,依然正确输出了’UTF-8’!

至此,系统编码问题已经全部结束。原来是我的服务器缺少可用的utf8编码环境造成的,亏我还以为是我的anaconda创建环境的时候配置造成的问题(因为python3.6和3.7的stdout编码方式不同),真是太坑了。




参考资料
[1] https://stackoverflow.com/questions/48743106/whats-ansi-x3-4-1968-encoding
[2] https://docs.python.org/zh-cn/3/whatsnew/3.7.html
[3] https://stackoverflow.com/questions/40113507/unicodeencodeerror-in-python3
[4] https://help.ubuntu.com/community/Locale
[5] https://www.linuxidc.com/Linux/2015-08/122501.htm

你可能感兴趣的:(环境配置与使用)