【问题标题】:Converting Unicode to in python [duplicate]将Unicode转换为python [重复]
【发布时间】:2012-11-21 02:39:41
【问题描述】:

可能重复:
Convert Unicode to 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 字符不会导致此错误的最佳方法是什么。我不想忽略这些字符。

【问题讨论】:

  • 那么,避免此内容中出现 Unicode 错误的最佳方法是什么?
  • 一般情况下,您希望尽早将数据解码为Unicode,然后在最后进行编码。我不确定您程序中的各个部分,但如果 entry 是包含文本的内容,请尝试 entry = result['Entry Text'].decode('utf8') 将其转换为 Unicode,然后在您阅读写作时,也许是 donotecontent.encode('utf8')。跨度>
  • @ColeJohnson 不,不是。 Unicode 和 UTF-8 是完全不同的东西。 UTF-8 是 Unicode 的一种编码格式,用于将 unicode 字符串表示为字节串。
  • 有很多带有 Unicode 引号、破折号和重音符号的英文数据。您输入的任何数据都可能包含非 ASCII 字符,而在您假设没有的那一天,有人会证明您错了,并且可能会对此感到非常不安。

标签: python unicode utf-8


【解决方案1】:

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

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

而且,编码必须是从sys.getdefaultencoding() 返回的内容。

sys.getdefaultencoding()默认返回'ascii',str()/unicode()强制转换时可能会抛出编码/解码异常。

如果你想通过str()unicode()进行str 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(),因为它让我更容易维护代码。

【讨论】:

    【解决方案2】:

    假设您使用的是 Python 2.x,请记住:有两种类型的字符串:strunicodestr 是字节字符串,而 unicode 是 unicode 字符串。 unicode 字符串可用于表示任何语言的文本,但要将文本存储在计算机中或通过电子邮件发送,您需要使用字节表示该文本。要使用字节表示文本,您需要一种编码格式。编码格式很多,Python默认使用ascii,但ascii只能表示少数字符,多为英文字母。如果您尝试使用 ascii 对带有其他字母的文本进行编码,您将得到著名的“outside ordinal 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 默认使用asciiunicode 转换为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-8ascii 字符兼容,Python 将始终尝试使用 自动编码/解码字符串ascii。如果你没有正确编码你的字符串,但你只使用 ascii 字符,一切都会正常工作。但是,如果由于某种原因某些 非 ascii 字符滑入您的消息中,您将收到错误消息,这会使错误更难检测。

    【讨论】:

    • 感谢您的详尽解释。
    【解决方案3】:

    记住:你不能解码一个 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

    【讨论】:

      猜你喜欢
      • 2018-08-29
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      • 2017-09-23
      • 2011-10-10
      • 2011-09-26
      • 2014-07-21
      • 2016-02-25
      相关资源
      最近更新 更多