Python中读取文件时报错UnicodeDecodeError
场景:文本处理
平台:linux red-hat python3.5
情景1:
with open(filename, 'r') as f:
for line in f:
print(line)
出现错误:
Traceback (most recent call last):
File "count_bleu.py", line 16, in
for line in f:
File "/nfs/project/tools/env/tf1.8_py3.5_all_luban/lib/python3.5/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 1: ordinal not in range(128)
原因:
当使用open方法时,若不设定参数encoding的值时,该方法会默认encoding为系统默认的编码格式,也即是在平台不指定编码方式的时候,平台默认的编码方式查看方式为以下两种。
import locale
print(locale.getpreferredencoding())
import sys
print(sys.platform)
print(sys.getdefaultencoding())
原文件的编码格式为UTF-8,系统默认的编码格式为ANSI,有些中文字符在两种编码格式下不统一,因此读文件时报错。
with open(filename, encoding='utf-8') as f:
for line in f:
print(line)
情景3:
a = b'\xe5\x94\xb1\xe6\xad\x8c'
a = a.decode("utf-8")
print(a)
解决办法:
使用PYTHONIOENCODING
运行python的时候加上PYTHONIOENCODING=utf-8,即
PYTHONIOENCODING=utf-8 python your_script.py1
重新定义标准输出:标准输出的定义如下:
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
打印日志的方法:
sys.stdout.write("Your content....")
平台: linux red-hat python2.7
情景1:
with open(filename , 'r') as f:
for line in f:
print(line)
使用open的默认方法,不会出问错
情景2:
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
print(line)
此时会出现以下错误:
Traceback (most recent call last):
File "count_bleu.py.1", line 13, in
with open(filename, encoding='utf-8') as f:
TypeError: 'encoding' is an invalid keyword argument for this function
原因:
open方法在python2版本里无encoding参数
解决办法:
import io
with io.open(filename, 'r', encoding='utf-8') as f:
for line in f:
print(line)
情景3:
s = 'π排球の'
b = s.encode('ascii')
出错:
Traceback (most recent call last):
File "", line 1, in
UnicodeDecodeError: 'ascii' codec can't decode byte 0xcf in position 0: ordinal not in range(128)
原因:
由于python基于ASCII处理字符的,当出现不属于ASCII的字符时,会出现错误信息
非ASCII字符无法使用ASCII编码转换成字节字符串且Latin-1和unicode编码方式不兼容
只有ascii字符集中的字符,三种编码方式得到的结果才完全一致。
一旦你的 Python 代码是用管道 / 子进程方式运行,sys.stdout.encoding 就会失效(ascii 字符集不能用来表示中文字符),让你重新遇到 UnicodeEncodeError
会出现:
第一:sys.stdout.encoding 的值变成了 None;
第二:Python 在 print 时会尝试用 ascii 去编码 unicode.
>>> s = 'abc'
>>> print(s.encode())
b'abc'
>>> print(s.encode('latin'))
b'abc'
>>> print(s.encode('utf-8'))
b'abc'
在进行同时包含 str 与 unicode 的运算时,Python 一律都把 str 转换成 unicode 再运算,当然,运算结果也都是 unicode。
Python2情况下的解决办法:
import sys
reload(sys)
sys.setdefaultencoding('utf8')
背景知识
Python有两种字符串,文本字符串和字节字符串。其中文本字符串类型直接被命名为str,内部采用Unicode字符集(兼容ASCII码),而字节字符串直接用来表示原始的字节序列(用print函数来打印字节字符串时,若字节在ASCII码范围内,则显示为ASCII码对应的字符,其余的则直接显示为16进制数),该类型的被命名为bytes
编码和解码就是str和bytes这两种字符串之间的互相转换
Str包含一个encode方法,用于使用特定编码将其转换成bytes,这称之为编码,bytes包含一个decode方法,也接受一个编码作为其必要参数,返回一个str,这一过程称为解码
为了解决编码问题,在python3中,所有的字符串都是使用Unicode编码,统一使用str类型来保存,而str类型没有decode方法
查看了输出编码
>>>import sys
>>>sys.stdout.encoding
‘ANSI_X3.4-1968’
为了保证输出不会在 linux 终端上显示乱码,需要设置好 linux 的环境变量:export LANG=en_US.UTF-8
—
参考链接
http://in355hz.iteye.com/blog/1860787
http://monsterhuan.iteye.com/blog/1948945
http://perfyy.blog.sohu.com/145845129.html
http://in355hz.iteye.com/blog/1860787