3

可能重复:
将 Unicode 转换为 UTF-8 Python

我是一个非常新的 python 程序员,正在编写我的第一个脚本。该脚本从 plist 字符串中提取文本,然后对其执行一些操作,然后将其打包为 HTML 电子邮件。

从一些条目中,我得到了可怕的 Unicode“outside ordinal 128”错误。

在阅读了尽可能多的关于编码和解码的信息后,我知道获得编码对我来说很重要,但我很难理解何时或如何准确地做到这一点。

有问题的变量首先使用 plistlib 引入,然后从 markdown 转换为 HTML,如下所示:

entry = result['Entry Text']
donotecontent = markdown2.markdown(entry)

后来,它像这样放在电子邮件中:

html = donotecontent + '<br /><br />' + var3
part1 = MIMEText(html, 'html')
msg.attach(part1)

我的问题是,确保此内容中的 Unicode 字符不会导致此错误的最佳方法是什么。我宁愿不忽略角色。

4

3 回答 3

11

对不起我的英语不好。我说中文/日文,每天都使用 CJK 字符。Ceron几乎解决了这个问题,因此我不会再谈论如何使用encode()/ decode()

当我们使用str()强制转换任何 unicode 对象时,它会将 unicode 字符串编码为字节数据;当我们用来unicode()转换str对象时,它会将字节数据解码为 un​​icode 字符。

而且,编码必须是从sys.getdefaultencoding().

默认情况下,默认sys.getdefaultencoding()返回'ascii',在做str()/ unicode()casting时可能会抛出编码/解码异常。

如果你想通过str()or进行 str <-> unicode 转换unicode(),以及使用 'utf-8' 进行隐式编码/解码,你可以执行以下语句:

import sys    # sys.setdefaultencoding is cancelled by site.py
reload(sys)    # to re-enable sys.setdefaultencoding()
sys.setdefaultencoding('utf-8')

它将导致稍后执行str()unicode()转换任何编码为 utf-8 的 basestring 对象。

但是,我更喜欢显式使用encode()/ decode(),因为它使代码维护对我来说更容易。

于 2012-11-21T04:40:01.973 回答
4

假设您使用的是 Python 2.x,请记住:有两种类型的字符串:strunicode. str是字节字符串,而是unicodeunicode 字符串。unicode字符串可用于表示任何语言的文本,但要将文本存储在计算机中或通过电子邮件发送,您需要使用字节表示该文本。要使用字节表示文本,您需要一种编码格式。编码格式有很多种,Python默认使用ascii,但是ascii只能表示几个字符,大多是英文字母。如果您尝试使用ascii对带有其他字母的文本进行编码,您将得到著名的“外部序数 128”。例如:

>>> u'Cerón'.encode('ascii')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 3:
 ordinal not in range(128)

如果使用 . 也会发生同样的情况str(u'Cerón'),因为 Python 默认使用ascii转换unicodestr.

要完成这项工作,您必须使用不同的编码格式。UTF-8是一种编码格式,可以将任何 unicode 文本表示为字节。要将u'Cerón'unicode 字符串转换为字节,您必须使用:

>>> u'Cerón'.encode('utf-8')
'Cer\xc3\xb3n'

这次没有错误。

现在,回到您的电子邮件问题。我可以看到您正在使用MIMEText,它接受已经编码的str参数,在您的情况下是html变量。MIMEText还接受指定使用哪种编码的参数。因此,在您的情况下,如果html是 unicode 字符串,则必须将其编码为utf-8并传递 charset 参数(因为HTMLText默认情况下使用 ascii):

part1 = MIMEText(html.encode('utf-8'), 'html', 'utf-8')

但要小心,因为如果html已经是 astr而不是unicode,那么编码将失败。这是 Python 2.x 的问题之一,它允许您对已经编码的字符串进行编码,但会引发错误。

要添加到列表中的另一个问题是utf-8ascii字符兼容,Python 将始终尝试使用ascii自动编码/解码字符串。如果你没有正确编码你的字符串,但你只使用ascii字符,一切都会正常工作。但是,如果由于某种原因某些非 ascii字符滑入您的消息中,您将收到错误,这使得错误更难检测。

于 2012-11-21T03:45:21.557 回答
0

记住:你不能解码一个 unicode,你不能编码一个 str

>>> u"\xa0".decode("ascii", "ignore")

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    u"\xa0".decode("ascii", "ignore")
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 0: ordinal not in range(128)


>>> "\xc2".encode("ascii", "ignore")

Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    "\xc2".encode("ascii", "ignore")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 0: ordinal not in range(128)

签出这个优秀的教程

于 2012-11-21T03:12:10.480 回答