有没有一种简单的方法可以让 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 而不是修改它的名字?

Jquery插入unicode而不是符号

c语言怎样才能输出中文???(最简单的方法)

有没有一种简单的方法可以用命令行重构 javascript 代码?

有没有一种简单的方法可以在 phonegap 中获得手机的指南针航向精度?