此文以Python 2.7为基础。(文中结果是正确的,懒得去翻源码理解有错的地方,请自行纠正,^_^!)

处理Python中文需要注意的问题: - 1.请在Python内部使用统一的编码,建议Unicode(如果你要兼容不同的I/O编码)或者(统一『UTF-8』这样不用来回转换); - 2.I/O端的编码(包括控制台及文件内容);为了保持数据的可移植性,在文件内容上请使用一致的UTF-8格式; - 3.文件系统目录编码与I/O编码有可能不一致;

unicode和str

在Python中有两种对象,unicode和str,Python内部使用两个字节表示unicode;

>>> s = "我是str"
>>> type(s)
<type 'str'>
>>> print s
我是str

>>> u = u"我是unicode"
>>> type(u)
<type 'unicode'>
>>> print u
我是unicode

repr() 可用这个查看字节码

>>> s = "我是str"
>>> s = "我是str"
>>> print repr(s)
'\xce\xd2\xca\xc7str'
>>> s
'\xce\xd2\xca\xc7str'
>>> print s.__repr__()
'\xce\xd2\xca\xc7str'

decode()/encode()

Python有两个函数decode(),用于将指定的编码转换成Unicode;encode()将Unicode转换成指定编码,要实现编码的转换可以通过如下方式:

# 假定a中目前是UTF8的编码格式,想转换成gb2312
a.decode('utf8').encode('gb2312')

非unicode->unicode->非unicode

有个defaultencoding 使用sys.getdefaultcoding()查看,很多问题都是这个家伙引起的,对它要有足够的认识,它默认是ascii

>>> import sys
>>> sys.getdefaultencoding()
'ascii'

控制台输入

如果是windows,这里默认将是CP936格式编码,可以通过设置命令行窗口的编码格式来改变,在窗口图标上点击右键,选择“默认值”,在打开的界面中设置“默认代码页”即可;

>>> s = raw_input()
我是控制台输入的
>>> s
'\xce\xd2\xca\xc7\xbf\xd8\xd6\xc6\xcc\xa8\xca\xe4\xc8\xeb\xb5\xc4'
>>> print type(s), s
<type 'str'> 我是控制台输入的

源文件编码

py文件的编码定义,在py文件首行, # coding=utf-8,可以告诉编辑器及python解释器,当前py文件的编码格式

# coding=utf-8

file_name = u"中文试验.txt" # 这里表示为Unicode,输出时会转换成I/O的编码

文件中定义字符串,u表示用Unicode在内存中保存此字符串;

参考资料:Defining Python Source Code Encodings https://www.python.org/dev/peps/pep-0263/

系统和输入输出(I/O)编码

# encoding=utf-8
import os
import sys
import locale

file_name = u"中文试验.txt" # 这里表示为Unicode,输出时会转换成I/O的编码
encoding = None

'''
    操作系统中的环境变量PYTHONIOENCODING,用于说明stdin/stdout/stderr的编码格式,
    此变量会被设置在sys.stdout.encoding,在py中可以直接访问。
    如果未设置PYTHONIOENCODING会自动使用操作系统的编码,
        如:中文Windows 10中是cp936;
        Linux会受环境变量$LANG的影响,如果:LANG=en_US.UTF-8,那么这里就是UTF-8
    如果sys.stdout.encoding的值找不到,则系统将使用sys.getdefaultencoding()所获取的值,一般是ascii;

'''


def set_encoding():
    print "PYTHONIOENCODING=%s" % (os.environ.get("PYTHONIOENCODING"))
    print "sys.stdout.encoding=%s" % (sys.stdout.encoding)
    print "sys.getdefaultencoding()=%s" % (sys.getdefaultencoding())
    print "locale.getdefaultlocale()[1]=%s" % (locale.getdefaultlocale()[1]) # 操作系统encoding
    print "locale.getpreferredencoding()=%s" % (locale.getpreferredencoding()) # 操作系统encoding

    global encoding
    if sys.stderr.encoding:
        encoding = sys.stderr.encoding
    else:
        encoding = sys.getdefaultencoding()


def input_data():
    # 将unicode转换为I/O支持的编码进行提示语的显示,读入到内存的为I/O的编码格式
    s = raw_input(u"请输入你的中文名字:".encode(encoding))

    fo = open(file_name, "wb+")
    fo.write(s) # 从I/O读入的编码格式不进行处理直接写入文件
                # 所以在中文Windows 10中默认是cp936
    fo.close()


def load_data():
    fo = open(file_name, "rb")
    s = fo.read() # 读入到内存后是I/O编码的格式
    fo.close()

    d = {"Chinese": s}

    # 注意:前半段是Unicode,输出时会自动转换;后半段是I/O编码,不用转换
    print u"Chinese:", (d["Chinese"])


set_encoding()
input_data()
load_data()

文件系统目录编码

文件目录操作必须知道当前系统使用的文件编码,可由sys.getfilesystemencoding()获取默认设置;在Windows 10中文版中是mbcs,在Linux中与LANG环境变量有关,有可能UTF-8,如果未设置LANG,将默认为US-ASCII

# encoding=utf-8
import sys
import os

encoding = None


def guess_encoding():
    global encoding
    if sys.stderr.encoding:
        encoding = sys.stderr.encoding
    else:
        encoding = sys.getdefaultencoding()
    print "sys.stderr.encoding=%s" % (sys.stderr.encoding)
    print "sys.getdefaultencoding()=%s" % (sys.getdefaultencoding())
    print "sys.getfilesystemencoding()=%s" % (sys.getfilesystemencoding())


def ls():
    dir = u"C:\\Users\\jilili\\Documents\\地形图\\"
    # 中文Windows 10中,默认读入的是mbcs编码的文件名,需要decode成unicode,再encode成操作系统编码
    files = os.listdir(dir.encode(sys.getfilesystemencoding())) 
    for f in files:
        print f.decode(sys.getfilesystemencoding()).encode(encoding)


guess_encoding()
ls()

[ 编辑 | 历史 ]
最近由“jilili”在“2017-02-11 03:03:06”修改