2

追溯:

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()
4

2 回答 2

2

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

另外根据您的评论:

但是,当我尝试这样做时仍然会出现错误:python场所.py>categories.txt,但当输出到终端时不会出现:python场所.py

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

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

工作示例,使用我的使用cp437编码的美国 Windows 控制台。源代码保存在“UTF-8 without BOM”中。值得指出的是,源代码字节是 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
üéâäàåçêëèïîì
于 2013-08-18T19:55:58.507 回答
1

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

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

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

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

于 2013-08-18T08:41:01.220 回答