- V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
jacklong
V2EX    Python

  •  
  •   jacklong
    jack-long 2015-01-11 16:43:36 +08:00 4608 次点击
    这是一个创建于 3997 天前的主题,其中的信息可能已经有所发展或是发生改变。

    关于Python的编码问题

    将中文字符解码
    s = string.decode(‘gbk’)

    将字符串转码为utf-8
    s.encode(‘utf-8’)

    查看解释器默认字符编码
    import sys
    sys.getdefaultencoding() # ascii

    修改默认编码(本次)
    reload(sys) # 解决报错问题
    sys.setdefaultencoding('utf8’)

    chstring = "中文字符"
    with open('test.txt','w') as f:
    ... f.write(chstring)
    ...
    mystring = chstring.encode('ascii')
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 0: ordinal not in range(128)

    问题:
    1, string.decode('gbk') 解码后的编码格式?(操作系统默认)
    2, 环境默认ascii环境下输入的中文字符, open(filename, 'w')可以正常写入, 而'中文字符'.encode('ascii')报错,所生成文件的编码格式是什么?怎么确定的?

    20 条回复    2015-01-11 22:52:24 +08:00
    roricon
        1
    roricon  
       2015-01-11 17:17:41 +08:00   1
    这个问题在py2和py3中的回答是不同的。
    但一般只有在py2中才会踩到坑,那我就给个py2的答案吧。
    1. 解码后的类型是 <unicode>,在写入file中的时候,会默认以<utf-8>来保存。
    2.见问题1,'中文字符'.encode 肯定会失败

    见下面这段
    ==========
    In [8]: a = '你好'

    In [9]: a
    Out[9]: '\xe4\xbd\xa0\xe5\xa5\xbd'

    In [10]: type(a)
    Out[10]: str

    In [11]: a.decode('utf-8')
    Out[11]: u'\u4f60\u597d'

    In [13]: print(a.decode('utf-8'))
    你好
    ==========
    实际上如果给一个中文字字符串<str>类型,实际上等同于如下步骤。
    a = u'你好'

    a = a.encode('utf-8')

    不知道这么说是否已经说明白了。
    9hills
        2
    9hills  
       2015-01-11 17:36:49 +08:00   2
    再次重复在我在多个地方阐述过的话:

    Python2 没有任何必要使用 sys.setdefaultencoding('utf8’)。

    他两个问题,你只需要知道 encode是Unicode -> xxx ,decode是 xxx -> Unicode 就好了。。
    zhicheng
        3
    zhicheng  
       2015-01-11 18:59:35 +08:00   2
    1,和具体的 codec 有关系,例子中的 gbk 如果用在 str 上应该会返回 unicode 类型,用在 unicode 上应该还是 unicode 。
    2,'中文字符'.encode('ascii') 这个是因为 ascii 这个 codec 无法处理 '中文字符' 这个 str 。

    所有的 encode 和 decode 都和具体的 codec 有关系,返回的结果即可以是 str 也可以是 unicode 。
    比如 'abcd'.encode('hex') 结果还是 str 。

    多看看文档。
    https://docs.python.org/2/library/codecs.html
    loading
        4
    loading  
       2015-01-11 19:05:01 +08:00 via Android
    @9hills 为什么我用了就能跑,不用就出错?
    Sylv
        5
    Sylv  
       2015-01-11 19:41:45 +08:00 via iPhone
    @zhicheng 返回的结果即可以是 str 也可以是 unicode?不对吧。
    应该是:
    str.decode() -> unicode
    unicode.encode() -> str
    str.encode() -> str.decode().encode() -> str
    unicode.decode() -> unicode.encode().decode() -> unicode
    Sylv
        6
    Sylv  
       2015-01-11 19:44:38 +08:00 via iPhone
    @loading 我也从来没用过 sys.setdefaultencoding,是有更正确的解决办法的。
    loading
        7
    loading  
       2015-01-11 19:48:16 +08:00 via Android
    @Sylv 求教。
    Sylv
        8
    Sylv  
       2015-01-11 20:02:53 +08:00   1
    @loading 不同报错要视情况解决的。
    基本思路是:任何可能是非 ascii 的 str 输入要 decode('utf-8') 为 unicode,内部处理时都用 unicode,要输出时或使用不支持 unicode 的方法时(例如 urllib.unquote)再 encode('utf-8') 为 str。
    hahastudio
        9
    hahastudio  
       2015-01-11 20:03:56 +08:00   1
    zhicheng
        10
    zhicheng  
       2015-01-11 20:34:18 +08:00
    @Sylv 出处?
    Sylv
        11
    Sylv  
       2015-01-11 21:28:00 +08:00 via iPhone
    @zhicheng
    Codec.encode(input[, errors])
    Encodes the object input and returns a tuple (output object, length consumed). While codecs are not restricted to use with Unicode, in a Unicode context, encoding converts a Unicode object to a plain string using a particular character set encoding (e.g., cp1252 or iso-8859-1).

    Codec.decode(input[, errors])
    Decodes the object input and returns a tuple (output object, length consumed). In a Unicode context, decoding converts a plain string encoded using a particular character set encoding to a Unicode object.

    https://docs.python.org/2/library/codecs.html
    zhicheng
        12
    zhicheng  
       2015-01-11 21:35:59 +08:00
    @Sylv 所以,你看过上面的文字了?
    013231
        13
    013231  
       2015-01-11 22:14:09 +08:00
    回答:

    1. str decode后得到的是unicode类型. unicode类型是对字符的抽象, 你无须关心它内部使用编码方式(可能是UCS-2或UCS-4, 编译时指定).

    2. interpreter里输入的文字, 编码方式由sys.stdin.encoding确定. ASCII不能编码汉字, 所以会报错.
    Sylv
        14
    Sylv  
       2015-01-11 22:15:47 +08:00
    @zhicheng
    有什么问题吗?
    那请你举个 str.encode(codecs) -> unicode 或者 unicode.decode(codecs) -> str 的例子。
    013231
        15
    013231  
       2015-01-11 22:17:32 +08:00
    PS: str是字节组, 对它encode没有意义.
    str解码(decode)后得到unicode, unicode编码(encode)后得到str.
    Sylv
        16
    Sylv  
       2015-01-11 22:31:43 +08:00
    @zhicheng 我明白你的意思了,你指的是 hex 等非 Unicode 相关的 codecs。我说的是楼主这种处理 Unicode 的情况。受教了。
    zhicheng
        17
    zhicheng  
       2015-01-11 22:33:18 +08:00   1
    @013231 不知道有 'abcd'.encode('hex') 和 'abcd'.encode('base64') ?

    @Sylv
    >>> help(''.encode)
    >>> help(''.decode)
    >>> help(u''.encode)
    >>> help(u''.decode)

    自己看下输出?
    013231
        18
    013231  
       2015-01-11 22:41:35 +08:00
    @zhicheng 你说的是, 我疏忽了. 只考虑了str和unicode转换时的状况.
    Sylv
        19
    Sylv  
       2015-01-11 22:48:19 +08:00
    @zhicheng
    'abcd'.encode('hex') 和 'abcd'.encode('base64') 输出都是 str,这和 str.encode(Unicode codecs) -> str 一致,没什么特别的。
    但我真没见过 str.encode -> unicode 的情况。
    zhicheng
        20
    zhicheng  
       2015-01-11 22:52:24 +08:00   1
    @Sylv 没什么不可能的,只是不需要尔已。
    >>> import codecs
    >>> from t import search_function
    >>> codecs.register(search_function)
    >>> type(''.encode('foobar'))
    <type 'unicode'>
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     901 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 18:49 PVG 02:49 LAX 10:49 JFK 13:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86