解释器和文件
python文件编码
查看文件自身编码
➜ encoding file file_encoding.py
file_encoding.py: UTF-8 Unicode text
文件本身的编码是
UTF-8
不声明文件编码
➜ encoding cat file_encoding.py
print '你好'
print u'你好'
➜ encoding python file_encoding.py
File "file_encoding.py", line 1
SyntaxError: Non-ASCII character '\xe4' in file file_encoding.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
默认解释器按照
ASCII编码来解码你好对应的UTF-8编码后字节串,所以报错了
声明文件编码为utf-8
➜ encoding cat file_encoding.py
# encoding: utf-8
print '你好'
print u'你好'
➜ encoding python file_encoding.py
你好
你好
# encoding: utf-8告诉解释器使用UTF-8来解码你好对应的UTF-8编码后字节串
文件编码声明不在第一行
➜ encoding cat file_encoding.py
# author zhujipeng
# encoding: utf-8
print '你好'
print u'你好'
➜ encoding python file_encoding.py
File "file_encoding.py", line 4
SyntaxError: Non-ASCII character '\xe4' in file file_encoding.py on line 4, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
解释器会读取文件的第一行来确定解析
python使用的编码,所以编码声明要放在第一行
vim修改文件编码声明
vim不会修改文件本身的编码
➜ encoding file file_encoding.py
file_encoding.py: UTF-8 Unicode text
➜ encoding cat file_encoding.py
# encoding: gbk
print '你好'
print u'你好'
➜ encoding python file_encoding.py
你好
浣犲ソ
字符串
你好在文件被解析时按照gbk进行了解码,utf-8进行了编码
模拟输入输出过程
保存
保存过程会将你输入的字符根据文件的编码转化为字节进行保存
>>> '你好'.encode('utf-8')
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> u'你好'.encode('utf-8')
'\xe4\xbd\xa0\xe5\xa5\xbd'
字符串和字节串
你好在编码为utf-8的文件中保存时是6个字节,一个中文在utf-8中用3个字节表示
解析
解析过程会根据你声明的文件编码将字节转化为内部编码unicode形式的字符存储在内存中
严格来说
unicode是字符集,UTF-16和UCS-2才是编码, 内存的地址也是以字节为单位的,所以其实内存中的字符也是按字节存储的 只是解析器(或者编译器)在处理时会以两个字节为单位进行处理,这个过程是透明的
>>> u'你好'.encode('utf-8').decode('gbk')
u'\u6d63\u72b2\u30bd'
字符串
你好在文件被解析时按照gbk解码为了3个字符,一个中文在gbk中用2个字节表示
输出
>>> '你好'.encode('utf-8').decode('gbk').encode('utf-8')
'\xe6\xb5\xa3\xe7\x8a\xb2\xe3\x82\xbd'
字符串
你好在输出到终端时会根据终端的编码utf-8进行编码,转换成了9个字节
显示
>>> print u'你好'.encode('utf-8').decode('gbk')
浣犲ソ
显示程序会将输出的9个字节按照终端的编码
utf-8进行编码,转换成了3个字符
乱码
由于字符串整个编码解码的过程中使用编码不一致,所以乱码了 而字节串存储和展示的编码一致,所以没有乱码
pycharm修改文件编码声明
pycharm会修改文件本身的编码
➜ encoding file file_encoding.py
file_encoding.py: ISO-8859 text
➜ encoding cat file_encoding.py
# encoding: gbk
print '���'
print u'���'
➜ encoding python file_encoding.py
���
你好
字节串和字符串
你好在cat输出时保持字节流不变, 进行展示时则被按照utf-8编码进行了解码
模拟输入输出过程
保存
保存过程会将你输入的字符根据文件的编码转化为字节进行保存
>>> '你好'.encode('gbk')
'\xc4\xe3\xba\xc3'
>>> u'你好'.encode('gbk')
'\xc4\xe3\xba\xc3'
字符串和字节串
你好在编码为gbk的文件中保存时是4个字节,一个中文在gbk中用2个字节表示
解析
解析过程会根据你声明的文件编码将字节转化为内部编码unicode形式的字符存储在内存中
严格来说
unicode是字符集,UTF-16和UCS-2才是编码, 内存的地址也是以字节为单位的,所以其实内存中的字符也是按字节存储的 只是解析器(或者编译器)在处理时会以两个字节为单位进行处理,这个过程是透明的
>>> u'你好'.encode('gbk').decode('gbk')
u'\u4f60\u597d'
字符串
你好在文件被解析时按照gbk解码为了2个字符,一个中文在gbk中用2个字节表示
输出
>>> u'你好'.encode('gbk').decode('gbk') .encode('utf-8')
'\xe4\xbd\xa0\xe5\xa5\xbd'
字符串
你好在输出到终端时会根据终端的编码utf-8进行编码,转换成了6个字节
显示
>>> print u'你好'.encode('gbk').decode('gbk') .encode('utf-8')
你好
显示程序会将输出的6个字节按照终端的编码
utf-8进行编码,转换成了2个字符
乱码
由于字符串整个编码解码的过程中使用的编码一致,所以没有乱码 而字节串存储和展示的编码不一致,所以乱码了
python文件读写
默认的文件写入
➜ encoding cat file_encoding.py
# encoding: utf-8
with open("test_file.txt", "wa") as f:
f.write("中")
f.write(u"中")
➜ encoding python file_encoding.py
Traceback (most recent call last):
File "file_encoding.py", line 4, in <module>
f.write(u"中")
UnicodeEncodeError: 'ascii' codec can't encode character u'\u4e2d' in position 0: ordinal not in range(128)
由于
python无法知道文件的编码,所以会使用默认编码ascii来对字符串中进行编码
改变的文件写入
➜ encoding cat file_encoding.py
# encoding: utf-8
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
with open("test_file.txt", "wa") as f:
f.write("中")
f.write(u"中")
➜ encoding python file_encoding.py
encoding cat test_file.txt
中中
设置默认编码为
utf-8就可以正常写入了
默认的文件读取
➜ encoding cat file_encoding.py
# encoding: utf-8
for line in open("test_file.txt", "r"):
print type(line), line
➜ encoding python file_encoding.py
<type 'str'> 中中
读取文件时返回的类型为字节串