【发布时间】:2013-05-16 21:52:19
【问题描述】:
我知道类似的问题已经被问过一百万次了,但是尽管阅读了其中很多,我还是找不到适合我情况的解决方案。
我有一个 django 应用程序,我在其中创建了一个管理脚本。该脚本读取一些文本文件,并将它们输出到终端(稍后它将对内容做更多有用的事情,但我仍在对其进行测试)并且字符以\xc3\xa5 之类的转义序列出现,而不是预期的å。由于该转义序列表示Ã¥,这是由于编码问题而对å 的常见误解,我怀疑至少有两个地方出错了。但是,我不知道在哪里 - 我已经检查了我能想到的所有可能的罪魁祸首:
- 终端编码为UTF-8;
echo $LANG给en_US.UTF-8 - 文本文件以 UTF-8 编码;
file *在它们所在的目录中导致所有条目都被列为“UTF-8 Unicode 文本”,除了一个不包含任何非 ASCII 字符并被列为“ASCII 文本”的条目。在该文件上运行iconv -f ascii -t utf8 thefile.txt > utf8.txt会生成另一个具有 ASCII 文本编码的文件。 - Python 脚本都是 UTF-8(或者,在某些情况下,是没有非 ASCII 字符的 ASCII)。我尝试在我的管理脚本中插入带有一些特殊字符的注释以强制它保存为 UTF-8,但它并没有改变行为。以上对文本文件的观察也适用于所有 Python 脚本文件。
- 处理文本文件的 Python 脚本顶部有
# -*- encoding: utf-8 -*-;前面唯一的一行是#!/usr/bin/python3,但我尝试将 Python 2.7 更改为.../python或将其完全删除以将其留给 Django,但没有结果。 - 根据the documentation,“Django 原生支持 Unicode 数据”,因此我“可以在应用程序的任何位置安全地传递 Unicode 字符串”。
我真的想不出任何其他地方可以在链中寻找非 UTF-8 链接。我在哪里可能错过了更改为 UTF-8 的设置?
为了完整起见:我正在使用 lines = file.readlines() 读取文件并使用标准 print() 函数进行打印。两端都没有手动编码或解码。
更新:
针对cmets的提问:
-
print(sys.getdefaultencoding(), sys.stdout.encoding, f.encoding)为所有文件生成('ascii', 'UTF-8', None)。 - 我开始编译一个 SSCCE,很快发现只有在尝试打印元组中的值时才会出现问题。换句话说,
print(lines[0].strip())工作正常,但print(lines[0].strip(), lines[1].strip())不行。添加.decode('utf-8')会生成一个元组,其中两个字符串都标有前面的u和\xe5(å的正确转义序列)而不是之前的奇数字符 - 但我不知道如何打印它们作为常规字符串,没有转义字符。我已经测试了对.decode('utf-8')的另一个调用以及在str()中的包装,但是两者都失败了UnicodeEncodeError抱怨\xe5不能用ascii 编码。由于单个字符串可以正常工作,我不知道还要测试什么。
SSCCE:
# -*- coding: utf-8 -*-
import os, sys
for root,dirs,files in os.walk('txt-songs'):
for filename in files:
with open(os.path.join(root,filename)) as f:
print(sys.getdefaultencoding(), sys.stdout.encoding, f.encoding)
lines = f.readlines()
print(lines[0].strip()) # works
print(lines[0].strip(), lines[1].strip()) # does not work
【问题讨论】:
-
是的,Django 原生支持 Unicode,你可以传递 Unicode 字符串……但最终,如果你正在读/写文件或 stdin/stdout,你必须在边缘进行编码/解码。
-
解码:
'\xc3\xa5'.decode('utf-8') == u'\xe5' -
无论如何,我的第一个建议是给我们一个SSCCE,这样我们就可以在你的代码中找到实际的错误,而不是仅仅试图猜测你可能做错了什么。其次,为每个文本模式文件(在 3.x 中)打印出
sys.getdefaultencoding()、sys.stdout.encoding和f.encoding。 -
一种可能的可能性是您将 Unicode 正确编码为 UTF-8,然后将该 UTF-8 打印为 Latin-1/CP819/等。
stdout。 (Blender 的编辑评论显示他比我早 4 分钟就在想同样的事情……) -
您必须回答我们为调试问题而提供的所有问题,而不是部分回答少数问题,否则我们无法为您调试问题。
标签: python django unicode utf-8