Python 2.7使用UTF-8头解码错误:UnicodeDecodeError:' ascii'编解码器不能解码字节0xc3

时间:2013-08-18 03:18:56

标签: python python-2.7 unicode utf-8

回溯:

Traceback (most recent call last):
  File "venues.py", line 22, in <module>
    main()
  File "venues.py", line 19, in main
    print_category(category, 0)
  File "venues.py", line 13, in print_category
    print_category(subcategory, ident+1)
  File "venues.py", line 10, in print_category
    print u'%s: %s' % (category['name'].encode('utf-8'), category['id'])
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 3: ordinal not in range(128)

代码:

# -*- coding: utf-8 -*-

# Using https://github.com/marcelcaraciolo/foursquare
import foursquare 

# Prints categories and subcategories
def print_category(category, ident):
    for i in range(0,ident):
        print u'\t',
    print u'%s: %s' % (category['name'].encode('utf-8'), category['id'])

    for subcategory in category.get('categories', []):
        print_category(subcategory, ident+1)

def main():
    client = foursquare.Foursquare(client_id='id',
                                   client_secret='secret')
    for category in client.venues.categories()['categories']:
        print_category(category, 0)

if __name__ == '__main__':
    main()

2 个答案:

答案 0 :(得分:2)

诀窍是,将所有字符串处理完全保留在源代码中。读取输入(文件/管道/控制台)时解码为Unicode,写入输出时进行编码。如果category['name']是Unicode,请保持这种方式(删除`.encode('utf8')。

同样根据你的评论:

  

然而,错误   当我尝试这样做时仍然会发生:python venues.py&gt; categories.txt,但是   当输出到终端时:python venues.py

Python通常可以确定终端编码并自动编码为该编码,这就是写入终端的原因。如果使用shell重定向输出到文件,则需要通过环境变量告诉Python所需的I / O编码,例如:

set PYTHONIOENCODING=utf8
python venues.py > categories.txt

工作示例,使用我的使用cp437编码的美国Windows控制台。源代码保存在“没有BOM的UTF-8”中。值得指出的是源代码字节是UTF-8,但声明源编码并使用Unicode字符串允许Python正确解码源,并自动编码print输出到终端使用其默认编码

#coding:utf8
import sys
print sys.stdout.encoding
print u'üéâäàåçêëèïîì'

这里Python使用默认的终端编码,但是在重定向时,不知道编码是什么,所以默认为ascii

C:\>python example.py
cp437
üéâäàåçêëèïîì

C:\>python example.py >out.txt
Traceback (most recent call last):
  File "example.py", line 4, in <module>
    print u'üéâäàåçêëèïîì'
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-12: ordinal not in range(128)

C:\>type out.txt
None

由于我们正在使用shell重定向,因此使用shell变量来告诉Python使用哪种编码:

C:\>set PYTHONIOENCODING=cp437

C:\>python example.py >out.txt

C:\>type out.txt
cp437
üéâäàåçêëèïîì

我们也可以强制Python使用其他编码,但在这种情况下,终端不知道如何显示UTF-8。终端仍在使用cp437解码文件中的字节:

C:\>set PYTHONIOENCODING=utf8

C:\>python example.py >out.txt

C:\>type out.txt
utf8
üéâäàåçêëèïîì

答案 1 :(得分:0)

我不确定,但我认为罪魁祸首是u"%s: %s"开头的“你”字符。这假设您要打印的是字节字符串而不是unicode字符串---这是合理的(*):输出字节,适当编码。修改如下:

print '%s: %s' % (category['name'].encode('utf-8'), category['id'])

这会将unicode字符串category['name']转换为UTF-8字节字符串,然后其余的处理完成字节字符串。

(*)从一个角度来看是合理的;另一种观点是打印unicode字符串并让环境决定它应该如何编码,但是你会受到几个你无法控制的因素的影响。这就是为什么你看到输出到终端或文件的差异。要避免所有这些问题,只需打印字节字符串。