有没有一种简单的方法可以让 unicode 在 python 中工作?
Posted
技术标签:
【中文标题】有没有一种简单的方法可以让 unicode 在 python 中工作?【英文标题】:Is there an easy way to make unicode work in python? 【发布时间】:2012-09-15 10:18:07 【问题描述】:我正在尝试处理 python 2.7.2 中的 unicode。我知道有.encode('utf-8')
的东西,但是当我添加它时,有 1/2 的时间会出错,而当我不添加它的时候,有 1/2 的时间会出错。
有什么方法可以告诉 python - 我认为是一种最新和现代的语言,只使用 unicode 作为字符串,而不是让我不得不放屁 .encode('utf-8')
的东西?
我知道...python 3.0 应该可以做到这一点,但我不能使用 3.0,而且 2.7 也不是那么旧...
例如:
url = "http://en.wikipedia.org//w/api.php?action=query&list=search&format=json&srlimit=" + str(items) + "&srsearch=" + urllib2.quote(title.encode('utf-8'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 19: ordinal not in range(128)
更新
如果我从我的所有代码中删除所有.encode
语句并将# -*- coding: utf-8 -*-
添加到我的文件顶部,就在#!/usr/bin/python
下方,那么我会得到以下内容,就像我没有添加# -*- coding: utf-8 -*-
一样全部。
/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py:1250: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
return ''.join(map(quoter, s))
Traceback (most recent call last):
File "classes.py", line 583, in <module>
wiki.getPage(title)
File "classes.py", line 146, in getPage
url = "http://en.wikipedia.org/w/api.php?action=query&prop=revisions&format=json&rvprop=content&rvlimit=1&titles=" + urllib2.quote(title)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 1250, in quote
return ''.join(map(quoter, s))
KeyError: u'\xf1'
我不是手动输入任何字符串,而是从网站解析 html 和 json。所以脚本/字节流/不管它们是什么,都是由python创建的。
更新 2 我可以继续处理错误,但它只是不断出现在新的地方。我希望 python 会成为一个有用的脚本工具,但看起来在 3 天没有运气之后我会尝试另一种语言。很遗憾,python 预装在 osx 上。我已将修复我发布的错误的一个实例的答案标记为正确。
【问题讨论】:
仅供参考,我刚刚发布了一个相关问题,深入探讨了这个问题的一个方面:***.com/questions/12557447/… 请阅读joelonsoftware.com/articles/Unicode.html。现在。如果一个人至少不理解本文中的内容,那么他根本无法使用 text 编写工作程序,更不用说正确处理编码转换了。从你的问题措辞可以看出你是在盲目尝试。 @jsbueno - 我知道 unicode 是什么,我知道它是如何工作的。 Python 将它推到了你必须盲目尝试使用它的地步。 不,你没有。如果您了解 Pytho 是如何工作的,那么 Pytho 的使用方式会非常合理,因为它在上面的链接中得到了很好的解释。 顺便说一句..请不要将其视为冒犯性评论。只需阅读这篇文章,您不仅会对手头的任务更有信心,而且不会只处理 Python 文本问题。 【参考方案1】:这是一个非常古老的问题,但只想添加一个部分建议。虽然我同情 OP 的痛苦——我自己经历了很多——但这是一个(部分)答案,可以让事情“更轻松”。把它放在任何 Python 2.7 脚本的顶部:
from __future__ import unicode_literals
这至少可以确保您自己的文字字符串默认为 unicode 而不是 str。
【讨论】:
这似乎是对 OP(主要)问题的最直接答案。【参考方案2】:实际上,让 Python 使用 unicode 的最简单方法是使用 Python 3,默认情况下所有内容都是 unicode。
不幸的是,为 P3 编写的库并不多,在编码和关键字使用方面也存在一些基本差异。这就是我遇到的问题:我需要的库仅适用于 P 2.7,我不知道将它们转换为 P 3。:(
【讨论】:
这是我对这个问题找到的最佳答案。【参考方案3】:除了在任何地方使用 unicode 字符串并立即解码您收到的任何编码字符串之外,没有办法让 unicode “正常工作”。问题是,无论您是在处理编码数据还是未编码数据,或者使用为您跟踪数据的工具,您都必须始终保持直截了当,否则您将度过一段糟糕的时光。
Python 2 为此做了一些有问题的事情:它使 str
成为“默认”而不是 unicode
用于字符串文字之类的东西,当您添加两者时,它会默默地将 str
强制转换为 unicode
,它允许您在已编码的字符串上调用 .encode()
以对其进行双重编码。因此,有很多 Python 编码器和 Python 库不知道他们设计使用什么编码,但仍然设计用于处理 some 特定编码,因为 @ 987654328@ 类型旨在让程序员自己管理编码。而且每次使用这些库时都必须考虑编码,因为它们本身不支持unicode
类型。
在您的特定情况下,第一个错误告诉您正在处理编码的 UTF-8 数据并尝试对其进行双重编码,而第二个错误告诉您正在处理未编码的数据。 看起来你可能两者都有。您确实应该找到并解决问题的根源(我怀疑这与我上面提到的无声强制有关),但这里有一个应该在短期内解决它的 hack:
encoded_title = title
if isinstance(encoded_title, unicode):
encoded_title = title.encode('utf-8')
如果这实际上是一种无声胁迫咬你的情况,你应该能够使用出色的 unicode-nazi 工具轻松找到问题:
python -Werror -municodenazi myprog.py
这将在 unicode 泄漏到您的非 unicode 字符串时为您提供追溯,而不是尝试从实际问题开始排除此异常。有关详细信息,请参阅我对 related question 的回答。
【讨论】:
嗯,这在一种方法中有效,但只是将错误移动到另一个位置。我想我会用另一种语言重写所有内容。我曾希望 python 能成为一个有用的脚本工具,3 天后,不。 如果这消除了你的错误,太好了!这证实了您的问题是 unicode 字符串与非 unicode 混合在一起。坏数据仍然存在于某个地方,另一个错误很可能只是同一原始问题的另一个症状。我刚刚更新了答案,提到了 unicode-nazi 工具,它应该可以让你轻松找出根本问题。 看起来HTMLParser
不做unicode?我只是不明白为什么处理 unicode 必须如此困难。它应该 100% 对开发人员隐藏,它是低级的东西。哎呀,甚至 obj-c 都将其隐藏起来,一切都可以正常工作。
isinstance
的东西也不适用于 def handle_data(self, data):
从 HTMLParser
类返回的数据。
在您处理的大多数情况下,它应该对开发人员隐藏,但有些人认为让这些事情变得更快更重要不是正确的,并且更改核心库的过程非常缓慢,以至于在 python 3 完成任何事情之前花了这么长时间。【参考方案4】:
是的,将您的 unicode 数据定义为 unicode 文字:
>>> u'Hi, this is unicode: üæ'
u'Hi, this is unicode: üæ'
您通常希望使用 '\uxxxx` unicode 转义或设置源代码编码。例如,模块顶部的以下行将编码设置为 UTF-8:
# -*- coding: utf-8 -*-
阅读Python Unicode HOWTO了解详细信息,例如默认编码等(默认源代码编码,例如,ASCII)。
至于您的具体示例,您的标题不是 Unicode 文字,而是 python 字节字符串,python 正在尝试为您解码它 to unicode,以便您可以再次对其进行编码。这失败了,因为这种自动编码的默认编解码器是 ASCII:
>>> 'å'.encode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
编码只适用于实际的 unicode 字符串,因此需要对字节字符串进行显式解码:
>>> 'å'.decode('utf-8').encode('utf-8')
'\xc3\xa5'
如果你习惯了 Python 3,那么 Python 2 中的 unicode 字面量 (u''
) 是 Python 3 中新的默认字符串类型,而 Python 2 (''
) 中的常规(字节)字符串与bytes
Python 3 中的对象 (b''
)。
如果在 title
上使用和不使用编码调用时都有错误,则说明数据混合。测试标题并根据需要进行编码:
if isinstance(title, unicode):
title = title.encode('utf-8')
您可能想找出产生混合 unicode/字节字符串标题的原因,并更正该来源以始终产生一个或另一个。
【讨论】:
嗨,我试过# -*- coding: utf-8 -*-
,但似乎什么也没做。
@Justin808:阅读链接的 HOWTO。哦,还有这个Joel Spolsky article。你的title
是字节串,不用encode
了。
这是在一个循环中,是否有多个title
?我怀疑 some 是 unicode,有些不是。
试试if isinstance(title, unicode): title=title.encode('utf-8')
;你几乎肯定有混合数据。【参考方案5】:
确保 title.encode("utf-8") 中的标题是 unicode 类型,不要使用 str("İŞşĞğÖöÜü")
在你的字符串化器中使用 unicode("ĞğıIİiÖöŞşcçÇ")
【讨论】:
如果没有明确的编码,你就做不到。unicode('å')
会以相同的UnicodeDecodeError
失败。以上是关于有没有一种简单的方法可以让 unicode 在 python 中工作?的主要内容,如果未能解决你的问题,请参考以下文章
有没有一种简单的方法可以让两个 jQuery 效果紧随其后?
有没有一种简单的方法可以让 emscripten 发出 wasm 而不是修改它的名字?