Python UnicodedecodeError编码问题解决方法汇总
作者:tomorrownan 发布时间:2023-10-07 09:28:20
今天真的被编码问题一直困扰着,午休都没进行。也真的见识到了各种编码。例如:gbk,unicode、utf-8、ansi、gb2312等。
如果脚本程序中编码与文件编码不一致,就会报出UnicodedecodeError的错误。
1.情景一
读文件时常需要将内容转为utf8,文字可正常显示,但是如果原文件内容编码格式不是utf8就会报错UnicodedecodeError。如下:
问题:
try:
fileObj = open(os.path.join(path,filename),'r')
textLines = fileObj.readlines()
fileObj.close()
except IOError as err:
print('打开文件%s失败:%s'%(filename,err))
解决方法:
代码改为:
try:
fileObj = open(os.path.join(path,filename),'r',encoding='utf-8')
textLines = fileObj.readlines()
fileObj.close()
except IOError as err:
print('打开文件%s失败:%s'%(filename,err))
此方法可以解决一部分编码问题,但是却不是一劳永逸的,在下一批文件因其他功能扩展需要读写时,上面程序又报出UnicodedecodeError:gbk codec cant decode…
2.情景二
针对上面的编码问题没有得到很好的解决,决定专门写一个批量将文件夹下面的文件编码格式改为utf-8的脚本,网上查资料得知python的第三方模块chardet,但是要安装这个扩展库。
chardet是一个非常好的编码识别模块,
1.chardet库的安装
在外网机上安装这个模块是特表简单的,直接执行pip chardet install命令即可,但是我的工作环境是内网,因为这个项目要处理的文件量多且大,所以也在Windows系统(编码问题比Linux多),因此安装chardet模块也花费了好大一会时间。
a.在外网下载好安装包chardet-3.0.4.tar.gz。
b.解压缩放在python安装路径\Python\Lib\site-packages下,命令切换到当前目录,执行python setup.py install。
c.安装完毕后import chardet仍然未成功
上面的安装步骤是没有问题的,我想应该是因为某个依赖没有安装吧,因此突然想到一个比较笨的方法:就是在外网机上执行pip chardet install先安装好,然后到安装目录下把关于chardet的安装目录chardet和chardet-3.0.4.dist-info拷贝到内网机\Python\Lib\site-packages下,再import chardet时竟然成功了。。。。
编写文件编码格式转换脚本
#!/usr/bin/python
# _*_ coding:utf-8 _*_
#更改文件编码,文件统一改为utf-8无BOM格式
import os
from chardet import detect
#文件夹目录
g_filedir = r'C:\Users\Desktop\nmg\SS'
def runcoding(path):
for filename in os.listdir(path):
if filename.endswith('.txt'):
with open(os.path.join(path,filename),'rb+') as fileObj:
fileContent = fileObj.read()
#判断编码格式
encodingtype = detect(fileContent)['encoding']
print(encodingtype)
#格式转换
fileContent = fileContent.decode(encodingtype).encode('utf8')
#写回文件
fileObj.seek(0)
fileObj.write(fileContent)
if __name__=="__main__":
runcoding(g_filedir)
在处理字符串时,常常会遇到不知道字符串是何种编码,如果不知道字符串的编码就不能将字符串转换成需要的编码。上面的chardet模块就能很好的解决这个问题。
此时当前文件夹下的文件顺利的进行了读写,再次readlines时没有报UnicodedecodeError问题。可以检测到gbk、Unicode、utf8、utf16、utf8(big)等编码,也不用再一个编码一个编码的去转换,一个文件一个文件的转换。以为编码问题终于一次性解决了。
但是。。。到另一个省份的一批文件要进行批量操作时,进行到第49个文件就终止了,又报出UnicodedecodeError:‘utf8’ codec cant decode问题。。。。用上面脚本对该省份文件夹下文件进行格式转换时报出错误:TypeError:decode() argument 1 must be str ,not None。
3.情景三
针对情景2的问题,仍要继续排查编码的问题,根据运行的情景二的脚本时报出的错误在脚本中添加代码,打印出返回None的文件名。
修正代码
#!/usr/bin/python
# _*_ coding:utf-8 _*_
#更改文件编码,文件统一改为utf-8无BOM格式
import os
from chardet import detect
#文件夹目录
g_filedir = r'C:\Users\Desktop\nmg\SS'
def runcoding(path):
for filename in os.listdir(path):
if filename.endswith('.txt'):
with open(os.path.join(path,filename),'rb+') as fileObj:
fileContent = fileObj.read()
#判断编码格式
encodingtype = detect(fileContent)['encoding']
#ansi编码检测结果为none
if encodingtype==None:
print(filename)
continue
#print(encodingtype)
#格式转换
fileContent = fileContent.decode(encodingtype).encode('utf8')
#写回文件
fileObj.seek(0)
fileObj.write(fileContent)
if __name__=="__main__":
runcoding(g_filedir)
然后定位到那个文件,记事本打开再另存为查看编码方式为ANSI,或者使用notpad++查看编码类型。
记事本默认是以ANSI编码保存文本文档的,而正是这种编码存在的bug招致了上述怪现象。假如保存时选择Unicode、Unicode (Big Endian)、UTF-8编码,就正常了。此外,假如以ANSI编码保存含有某些特别符号的文本文档,再次打开后符号也会变成英文问号。
这里可以得知,文件以ansi编码时decode()函数返回的事None。
4. chardet模块detect()函数
chardet模块中的chardet.detect()函数可以检测编码。返回结果如下:
data = '我最美'.encode('gbk')
chardet.detect(data)
Out[103]: {'confidence': 0.73, 'encoding': 'ISO-8859-1', 'language': ''}
输出结果confidence为概率。
encoding为字符串的编码方式。
编码问题最困扰人,好在今天顺利解决了,各个省份的数据也都按照格式要求修改完毕,已经上报到各省份,晚上就花点时间整理以下喽。
来源:https://blog.csdn.net/w1418899532/article/details/84308049
猜你喜欢
- 网站中很多表单都会用到上传图片,logo,照片,用户也会上传图片,这个时候网站就需要一个上传图片的功能,而且在上传后希望能预览一下看上传的对
- 首先创建一个表Use Test;Create Table TableTest(`ID` mediumint(8) default '
- 在默认情况下,大多数浏览器都会将有序列表中的数字序列的与其列表文字内容显示为相同的字体。这篇快速教程将教你如何使用有序列表(ol)和段落(p
- 零、本讲学习目标了解面向对象编程思想掌握类和对象的定义和使用了解Python中的对象一、面向对象(一)程序员“面向对象”在现实世界中存在各种
- 可能出现的原因有:◆源数据库或目标数据库为 SQL Server 6.5 版。连接到 Access 项目的当前 SQL 服务器和要将数据库转
- SQL Server数据库的六个实用技巧:(一)挂起操作在安装Sql或sp补丁的时候系统提示之前有挂起的安装操作,要求重启,这里往往重启无用
- 问题:由于自己做项目的时候,需要循环的绘制数据,假设有100个样本,每个样本包含两个坐标点(A, B),我需要对这两个点标上不同的颜色,同时
- HTTP-REFERER这个变量已经越来越不可靠了,完全就是可以伪造出来的东东。 以下是伪造方法:ASP/Visual Basic代码 di
- 昨天在网上看到一个防采集软件,说采集只访问当前网页,不会访问网页的图片、JS等,今天突然想到,通过动态程序和Js访问分别记录访问者的IP,然
- 本文系统的对HTTP Headers进行了简明易懂的阐述,我仅稍作笔记。什么是HTTP HeadersHTTP是“Hypertext Tra
- 出差到了中国雅虎,这里的风格和淘宝很不一样。和雅虎一比,淘宝的办公环境就是个菜市场,闹哄哄,到处是人,在走道里狂奔乱窜,在每个会议室争得面红
- 对很多从事产品工作的同事来说,“以用户为中心”是工作的重点,同时也是难点。用户的心思难以捉摸,用户研究的工作也似乎高深莫测。不过,用户研究并
- 下面这个函数使用FSO对象来判断服务器上的某个文件是否存在:<%Private Function Dir(byVa
- php代码很简单:$server="127.0.0.1";println("Begin");$lin
- ASP正则表达式,RegExp对象提供简单的正则表达式支持功能。RegExp对象的用法: Function RegExpTest(
- 1.由于设置了slave的配置信息,mysql在数据库data目录下生成master.info,所以如有要修改相关slave的配置要先删除该
- 1. 引言今天来给小伙伴推荐两款实用的便于调试Python代码的工具,可以方便展示我们调试代码的中间状态,提升大家的编码效率。2. 动机在日
- asp之家注:学习asp,无论是做企业网站还是做个人网站一般都需要用到IP地址。如留言要记录留言者IP,用户登录也经常记录登录的IP,还有站
- 每个PHP脚本都限制了执行时间,所以我们需要通过 set_time_limit 来设置一个脚本的执行时间为无限长;然后使用 flush()
- 简单说明:思路:从数据岛menuXML中读取数据,从树的根节点开始分析树,利用 hasChildNodes() [方法:是否含有子节点 ]