碰到的错误
luffy在用python读取和保存字符串时, 经常碰到这样的错误(弱智错误):
>>> str1 = u'中文'
>>> with open("./output.txt", mode='wb') as f:
... f.write(str1)
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: a bytes-like object is required, not 'str'
encode()
在mode='wb’的情况下, f.write()只能接受bytes类型的对象, 那么怎么把Unicode字符串转为bytes呢?
python3中是这样做的:
>>> str1 = '中文'
>>> b_str1 = str1.encode('utf-8') #直接encode()也可, 经测试, 在linux上默认编码方式'utf-8', 在win7上默认编码为'gbk'
>>> with open('./out.txt', 'wb') as f:
... f.write(b_str1)
decode()
OK, 成功把Unicode字符串转化为bytes, 并且写入了文件. 在读取文件的时候, 需要按照和编码方式对应的解码方式进行解码.
>>> with open('./out.txt', mode='rb') as f: #以bytes字节流读取文本
... b_str1 = f.read()
... str1 = b_str1.decode('utf-8') #按照'utf-8'格式对字节流解码, 如果用其他格式如'gbk'则会出错
... print(b_str1)
... print(str1)
b'\xe4\xb8\xad\xe6\x96\x87'
'中文'
也可以在打开文件的时候指定解码方式
>>> with open('./out.txt', mode='r', encoding='utf-8') as f: #读取字节流, 以'utf-8'格式解码
... str1 = f.read() #得到的是已经编码字符串
sys.getdefaultencoding()和 sys.setdefaultencoding()
python3默认字符串编码格式为’utf-8’
>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
python3从sys模块中移除了setdefaultencoding()方法, 也就是说, 不允许设置为其他的默认编码格式. 见官方文档
关于Unicode和utf-8, utf-16的区别和联系
luffy一开始对Unicode和utf-16也是混淆的, 还尝试过str.encode('unicode')
这种操作, 简直…
查看wiki: Unicode is a computing industry standard for the consistent encoding, representation, and handling of text expressed in most of the world’s writing systems.
Unicode是计算机界对全球绝大多数字符表示的一个标准, 常用字符用16位二进制数表示, 其他生僻字用32位二进制数表示, 但是, 切记!这只是现实世界工业界定的标准, 在计算机磁盘里面并不是直接这么存的. 具体在计算机存储的时候, 有utf-8, utf-16, utf-32, 还有中文编码常用的gbk, gb2312; 日文韩文都有自己的编码标准. 这些都是对Unicode编码的映射方式.
在内存中, 不管文本之前的编码格式如何, 在执行str.decode(‘xxx’)之后, 统统解码为Unicode编码, 然后才能在终端显示.
在将字符串写入磁盘, 或者通过网络传输的时候, 需要将Unicode编码的字符串转为需要的格式, 比如utf-8在进行网络传输的时候性能较好; utf-16在windows下编程的时候较方便.
参考
参考的几篇文章都不错, 从各个角度解答了我的一些疑惑.
- 下面两篇文章解答了我对Unicode和UTF的疑惑
Unicode、UTF-8、UTF-16之间的区别
python3中编码与解码之Unicode与bytes - 下面两篇文章解答了我对python字符串编码和解码的疑惑
Python3 字符编码
【Python3】字符解码与编码 - 解答了python3默认编码解码方式的问题
Python3异常-AttributeError: module ‘sys’ has no attribute 'setdefaultencoding