有没有一种简单的方法可以在python中使unicode工作?

时间:2012-09-23 22:34:31

标签: python unicode utf-8 python-2.7

我正在尝试在python 2.7.2中处理unicode。我知道有.encode('utf-8')的东西,但是我添加它的时间是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天后我会尝试不同的语言。很遗憾,在osx上预装了python。我已经标记了修正我发布的错误的一个实例的答案。

5 个答案:

答案 0 :(得分:19)

这是一个非常古老的问题,但只是想添加一个部分建议。虽然我同情OP的痛苦 - 我自己也经历了很多 - 这是让事情变得“更容易”的一个(部分)答案。把它放在任何Python 2.7脚本的顶部:

from __future__ import unicode_literals

这至少可以确保您自己的文字字符串默认为unicode而不是str。

答案 1 :(得分:17)

除了在任何地方使用unicode字符串并立即解码您收到的任何编码字符串之外,没有办法使unicode“正常工作”。问题是,无论您是处理编码数据还是未编码数据,还是使用能够为您跟踪数据的工具,或者您将度过一段美好时光,您都必须保持直线。

Python 2做了一些有问题的事情:它使str为“默认”而非unicode等字符串文字之类的东西,它默默地将str强制转换为{{1}当你添加两个时,它允许你在已经编码的字符串上调用unicode来对其进行双重编码。因此,有很多python编码器和python库不知道他们设计的编码是什么,但仍然设计用于处理某些特定编码,因为{ {1}}类型旨在让程序员自己管理编码。每次使用这些库时都必须考虑编码,因为它们本身不支持.encode()类型。


在您的特定情况下,第一个错误告诉您正在处理编码的UTF-8数据并尝试对其进行双重编码,而第二个错误则告诉您正在处理未编码的数据。 看起来就像你可能同时拥有它们一样。你应该找到并解决问题的根源(我怀疑它与我上面提到的无声强制有关),但这是一个应该在短期内修复它的黑客:

str

如果这实际上是一个无声强制的情况,你应该能够使用优秀的unicode-nazi工具轻松追踪问题:

unicode

这将在unicode泄漏到非unicode字符串的时候给你回溯,而不是尝试从实际问题中排除这种异常方式。有关详细信息,请参阅此related question的答案。

答案 2 :(得分:3)

是的,将您的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正试图将它解码为 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中的常规(字节)字符串('')与Python 3中的bytes对象(b'')相同。

如果title上有和没有编码调用都有错误,则表示您有混合数据。测试标题并根据需要进行编码:

if isinstance(title, unicode):
    title = title.encode('utf-8')

您可能想知道产生混合unicode /字节字符串标题的原因,并纠正该源以始终产生一个或另一个。

答案 3 :(得分:2)

确保title.encode(“utf-8”)中的标题是unicode的类型,不要使用str(“İŞşĞğÖöÜü”)

在你的字符串中使用unicode(“ĞğıIİiÖöŞşcçÇ”)

答案 4 :(得分:2)

实际上,使用unicode实现Python的最简单方法是使用Python 3,默认情况下一切都是unicode。

不幸的是,没有很多为P3编写的库,以及编码和编写的一些基本差异。关键字使用。这就是我遇到的问题:我需要的库仅适用于P 2.7,我不知道将它们转换为P 3. :(

相关问题