Python:将UTF-8字符串转换为Latin-1

26

我在尝试使用 Python 2.5 更改编码时遇到了困难。

我有一个 XML 响应,我将其编码为 UTF-8:response.encode('utf-8')。这很好,但使用此信息的程序不喜欢这种编码,我必须将其转换为其他代码页。真实的例子是,我使用 ghostscript python 模块将 pdfmark 数据嵌入 PDF 文件中 - 最终结果在 Acrobat 中出现了错误的字符。

我已经用 .encode().decode() 在 'utf-8' 和 'latin-1' 之间进行了多种组合,但我无法输出正确的结果,让我感到非常困扰。

如果我使用.encode('utf-8')将字符串输出到文件中,然后使用 i.e. iconv.exe 将该文件从 UTF-8 转换为 CP1252(也称为 latin-1),并嵌入数据,则一切都正常。

基本上,有人可以帮助我将 UTF-8 编码为十六进制 C3 A1 的字符 á 转换为十六进制 E1 的 latin-1 吗?


19
CP1252 不是 Latin1 编码! - tchrist
1
好的,有一些小差异:http://zh.wikipedia.org/wiki/ISO/IEC_8859-1 - romor
8
将Unicode转换为Latin1最准确的方法是这样的:s = "ALL INFORMATION IRRECOVERABLY LOST"。我相信你会发现这种算法比你尝试的任何其他算法都要快,也更加诚实。 - tchrist
我试图使用latin1编码大写字母"Ñ",但失败了,其他字母都是正确的。不过,cp1252编码成功了!:D - Joeya
4个回答

25

不要使用.encode('utf-8'),而应使用.encode('latin-1')


谢谢。我简直不敢相信它如此简单,而我之前在做什么?我以前尝试过,但一直使用.encode('latin-1', 'ignore'),就像我在编码'ascii'时使用的那样。 - romor
2
上面的评论没有意义。现在两种方法(带或不带“忽略”)都正常工作了:o谢谢大家。我需要睡觉:| - romor
3
@funtuku:tchrist想要告诉你的是,无知并不是福,忽略一个未编码的字符也不是更好的选择。Unicode字符中有数万个(仅计算BMP),这些字符无法在latin1的192个字符集和64个控制字符中编码,而且没有.encode参数与“ignore”类似,因此... - John Machin
这个答案对于 Python 3 是错误的。如果 s 包含一个非 Latin-1 字符,s.encode('latin-1') 将会抛出异常。例如,'commander’s'.encode('latin-1') 会抛出异常,但是 'commander’s'.encode('utf-8') 不会。 - Prof Mo
@ProfMo 这不是一个错误,而是一个特性。如果你愿意,你可以轻松地丢弃异常,但你不应该这样做,因为这样做会丢失数据。 - wizzwizz4

6
data="UTF-8 data"
udata=data.decode("utf-8")
data=udata.encode("latin-1","ignore")

应该这样做。


3
@Ned:只有在不丢弃错误的情况下,转换为Latin-1才可以。 - tchrist
2
@Ned,据我所知,OP的情况还有其他问题,因为Acrobat应该对Unicode没有问题。他一定是将UTF-8写入到已经是ISO-8859-1的文件中,这意味着他选择了错误的编码方式。但他需要检测错误,因为它们意味着他无法做他想做的事情,而是需要将原始文档升级到更大的字符集。 - tchrist
3
在工作中,我每天都需要处理被无知程序员搞砸的带有“?”字符的文本文件,这让我非常恼火! - tchrist
1
@tchrist:我明白有时这是必要的。下次请不要攻击另一个想法,而是尝试解释在那种情况下为什么您的解决方案是更好的选择。 - Utku Zihnioglu
3
如果我运行您的代码,会出现错误:AttributeError: 'str' object has no attribute 'decode'。该错误提示字符串对象没有"decode"属性。 - HelloGoodbye
显示剩余7条评论

4

您能提供更多关于您所尝试做的事情的细节吗?一般而言,如果您有一个Unicode字符串,可以使用编码将其转换为具有适当编码的字符串。例如:

>>> a = u"\u00E1"
>>> type(a)
<type 'unicode'>
>>> a.encode('utf-8')
'\xc3\xa1'
>>> a.encode('latin-1')
'\xe1'

0
如果之前的答案不能解决你的问题,检查一下数据源是否无法正确打印/转换。
在我的情况下,我错误地使用了json.load来读取文件中的数据,没有使用encoding="utf-8"。试图将结果字符串进行解/编码为latin-1是无济于事的...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接