Python
编写,因此又拾起了很久没有写的 Python
,让我无语的是总是遇到各种中文乱码的问题,所以趁着周末,总结一下遇到的中文乱码问题和对应的解决方案,以及为什么会出现中文乱码的问题。1、SyntaxError: Non-ASCII character '\xe4' in file XXX
2、UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 0: ordinal not in range(128)
3、......
Python
版本 2.7.py
文件的编码格式为UTF-8,Python2
默认使用ASCII解码:# 例一
s = "hello"
print s
// 正常执行
hello
# 例二
s = "你好"
print s
// 执行失败
SyntaxError: Non-ASCII character '\xe4' in file XXX
UTF-8 是一种向后兼容的编码方式。如果文件中只包含 ASCII 字符,那么该文件符合 UTF-8 编码规范。这种特性使得使用 UTF-8 编码时,与使用 ASCII 编码的现有系统可以很好地协同工作。
# coding=utf-8
s = "你好"
print s
// 正常执行
你好
# coding=utf-8
import xlwt
comment_list = [["标题", "序号"], [1, 2]]
code = "1234"
# Create a new workbook and add a sheet
workbook = xlwt.Workbook()
sheet = workbook.add_sheet('Sheet1')
for row_index, row_data in enumerate(comment_list):
for col_index, cell_data in enumerate(row_data):
sheet.write(row_index, col_index, cell_data)
workbook.save('./%s.xls' % code)
// 程序执行报错
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
'ascii' 无法解码字节 0xe6 (UTF-8中的中文字符)
// 如果写入的数据中没有中文数据是可以正常执行的
// 我们看下这个对象的构造器:workbook = xlwt.Workbook() 可以看到默认使用的是 ascii 编码,而我们传入的数据是 UTF-8 (包含中文字符),因此无法解析
#################################################################
## Constructor
#################################################################
def __init__(self, encoding='ascii', style_compression=0):
self.encoding = encoding
self.__owner = 'None'
self.__country_code = None # 0x07 is Russia :-)
self.__wnd_protect = 0
self.__obj_protect = 0
Workbook
编码调整为相同即可,比如调整为utf-8
:# coding=utf-8
import xlwt
comment_list = [["标题", "序号"], [1, 2]]
code = "1234"
# Create a new workbook and add a sheet
workbook = xlwt.Workbook(encoding="utf-8")
sheet = workbook.add_sheet('Sheet1')
for row_index, row_data in enumerate(comment_list):
for col_index, cell_data in enumerate(row_data):
sheet.write(row_index, col_index, cell_data)
workbook.save('./%s.xls' % code)
utf-8
编码,你想用 gbk
编码怎么实现呢?其实中心思想是相同的,只要保证编码格式一致即可:# coding=utf-8
import sys
import xlwt
comment_list = [["标题", "续保"], [1, 2]]
print "default encoding:", sys.getdefaultencoding()
# Create a new workbook and add a sheet
workbook = xlwt.Workbook(encoding="gbk")
sheet = workbook.add_sheet('Sheet1')
for row_index, row_data in enumerate(comment_list):
for col_index, cell_data in enumerate(row_data):
sheet.write(row_index, col_index, str(cell_data).decode("utf-8"))
code = "1234"
workbook.save('./%s.xls' % code)
// 程序执行正常
default encoding: ascii
Python2
字符串的两种表现形式gbk
方式中这段代码 str(cell_data).decode("utf-8")
有点疑惑,这其实涉及到 Python2
字符串的两种表现形式。1、str: 表示字节序列,是原始的字节串,而不涉及字符编码。
2、unicode: 表示 Unicode 字符串,用于处理字符编码和文本
示例:
# 在 Python 2 中,默认创建的是字节串而不是 Unicode 字符串
byte_str = "Hello, World!"
print type(byte_str) # 输出
# 创建 Unicode 字符串
unicode_str = u"你好"
print type(unicode_str) # 输出
# 从 str 转换成 unicode
print byte_str.decode('utf-8')
# 从 unicode 转换成 str
print unicode_str.encode('utf-8')
str
到 unicode
使用 decode
,而 unicode
转换成 str
使用 encode
,其实这是因为 Python
认为 16 位的 unicode
才是字符的唯一内码,而大家常用的字符集如 gb2312
,gb18030/gbk
,utf-8
,以及 ascii
都是字符的二进制(字节)编码形式。因此从 unicode
到其它二进制编码格式都使用 encode
。str(cell_data).decode("utf-8")
写法的原因# 转换为 str 类型
str(cell_data)
# 这里为什么么需要先 decode("utf-8") 转为 unicode
# 实际上 Python 运行时并不知道 str 的编码,因此需要开发者指定正确的编码方式进行解码
# 如果开发者不指定编码方式进行手动解码则会使用 sys.getdefaultencoding() 配置的值 ascii 进行解码
str(cell_data).decode("utf-8")
# 由于我们在程序开头指定了编码方式为 utf-8 即 str 的编码格式,如果这样写:
sheet.write(row_index, col_index, cell_data)
程序执行异常:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
因为 ascii 编码无法解析带有中文的 utf-8 编码
gbk
,当按照 utf-8
字符集打印时,控制台无法解析,出现乱码。Python2.7
中出现的一些乱码案例出发,从字符编码、Python2.7
字符原理分析了中文乱码、编码问题导致的原因并给出相应的解决方案,实际上在编码乱码分析这一块在其它语言上也是共通的,可以作为一定的参考依据。一些建议:
1、Python3 以前使用字符串,建议都带上前缀u,在 Python 3 中,字符串默认是 Unicode。Unicode 支持编码自动转换。
// 比如同样是上文的案例,你不再需要解码
# coding=utf-8
import sys
import xlwt
comment_list = [[u"标题", u"续保"], [1, 2]]
print "default encoding:", sys.getdefaultencoding()
# Create a new workbook and add a sheet
workbook = xlwt.Workbook(encoding="gbk")
sheet = workbook.add_sheet('Sheet1')
for row_index, row_data in enumerate(comment_list):
for col_index, cell_data in enumerate(row_data):
sheet.write(row_index, col_index, cell_data)
code = "1234"
workbook.save('./%s.xls' % code)
2、不要用str()函数,使用unicode()代替。
3、不要用过时的 string 模块(string 模块已经停止了更新,只保留了 ASCII 码的支持,不再推荐使用,Python 保留该模块仅仅是为了向后兼容)
4、非必要时,不需要对 unicode 字符进行编码,因为大多数情况会自动编码解码。
你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
我对技术的热情是我不断学习和分享的动力。我的博客是一个关于Java生态系统、后端开发和最新技术趋势的地方。
作为一个 Java 后端技术爱好者,我不仅热衷于探索语言的新特性和技术的深度,还热衷于分享我的见解和最佳实践。我相信知识的分享和社区合作可以帮助我们共同成长。
在我的博客上,你将找到关于Java核心概念、JVM 底层技术、常用框架如Spring和Mybatis 、MySQL等数据库管理、RabbitMQ、Rocketmq等消息中间件、性能优化等内容的深入文章。我也将分享一些编程技巧和解决问题的方法,以帮助你更好地掌握Java编程。
我鼓励互动和建立社区,因此请留下你的问题、建议或主题请求,让我知道你感兴趣的内容。此外,我将分享最新的互联网和技术资讯,以确保你与技术世界的最新发展保持联系。我期待与你一起在技术之路上前进,一起探讨技术世界的无限可能性。
保持关注我的博客,让我们共同追求技术卓越。