我是一个非常新的python程序员,正在处理我的第一个脚本。该脚本从plist字符串中提取文本,然后对其执行一些操作,然后将其打包为HTML电子邮件。
从一些条目中,我得到了可怕的Unicode"在序号128"之外错误。
尽可能多地阅读有关编码和解码的内容,但我知道对我来说编码很重要,但我很难理解何时或如何准确地执行此操作。< / p>
首先使用plistlib拉入违规变量,并从markdown转换为HTML,如下所示:
entry = result['Entry Text']
donotecontent = markdown2.markdown(entry)
稍后,它将被放入这样的电子邮件中:
html = donotecontent + '<br /><br />' + var3
part1 = MIMEText(html, 'html')
msg.attach(part1)
我的问题是,对于我来说,确保此内容中的Unicode字符不会导致此错误的最佳方法是什么。我不想忽视这些角色。
答案 0 :(得分:11)
抱歉我的英语不好。我说中文/日文,每天使用CJK字符。
Ceron几乎解决了这个问题,因此我不再讨论如何再次使用encode()
/ decode()
。
当我们使用str()
来转换任何unicode对象时,它会将unicode字符串编码为bytedata;当我们使用unicode()
来转换str
对象时,它会将bytedata解码为unicode字符。
并且,编码必须是从sys.getdefaultencoding()
返回的内容。
默认情况下,sys.getdefaultencoding()
默认返回'ascii',执行str()
/ unicode()
投射时可能会抛出编码/解码异常。
如果你想做str&lt; - &gt; 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的basetring对象。
但是,我更乐意明确使用encode()
/ decode()
,因为它可以让我更轻松地维护代码。
答案 1 :(得分:4)
假设您使用的是Python 2.x,请记住:有两种类型的字符串:str
和unicode
。 str
是字节字符串,而unicode
是unicode字符串。 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 将unicode
转换为str
。
要使其工作,您必须使用不同的编码格式。 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
已经是str
而不是unicode
,则编码将失败。这是Python 2.x的问题之一,它允许您对已编码的字符串进行编码,但它会引发错误。
添加到列表中的另一个问题是 utf-8 与 ascii 字符兼容,Python将始终尝试使用自动编码/解码字符串ASCII 。如果您没有正确编码字符串,但只使用 ascii 字符,那么一切都会正常工作。但是,如果由于某种原因某些非ascii 字符滑入您的邮件,您将收到错误,这会使错误更难以检测。
答案 2 :(得分: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)
结帐这个优秀的tutorial