【问题标题】:UnicodeDecodeError: 'utf8' codec can't decode byte 0x9a in position 12UnicodeDecodeError:“utf8”编解码器无法解码位置 12 中的字节 0x9a
【发布时间】:2017-11-03 14:45:01
【问题描述】:

我正在使用 chatterbot 库开发一个聊天机器人。聊天机器人是我的母语 --> 斯洛文尼亚语,其中有很多奇怪的字符(例如:š、č、ž)。我正在使用 python 2.7。

当我尝试训练机器人时,库遇到了上述字符的问题。例如,当我运行以下代码时:

chatBot.set_trainer(ListTrainer)
chatBot.train([
            "Koliko imam še dopusta?",
            "Letos imate še 19 dni dopusta.",
        ])

它会抛出以下错误:

UnicodeDecodeError: 'utf8' codec can't decode byte 0x9a in position 12: invalid start byte

我在文件顶部添加了# -*- coding: utf-8 -*- 行,我还通过我的编辑器(Sublime text 3)将所有使用文件的编码更改为 utf-8,我使用以下代码更改了系统默认编码:

import sys
reload(sys)
sys.setdefaultencoding('utf8')

字符串的类型是 unicode

当我尝试使用这些奇怪的字符获得响应时,它可以工作,它们没有任何问题。例如,在与上述训练代码相同的执行过程中运行以下代码(当我在训练字符串中将 'š' 更改为 's' 并将 'č' 更改为 'c' 时),不会引发错误:

chatBot.set_trainer(ListTrainer)
chatBot.train([
            "Koliko imam se dopusta?",
            "Letos imate se 19 dni dopusta.",
        ])    
chatBot.get_response("Koliko imam še dopusta?")

我找不到此问题的解决方案。有什么建议么? 提前感谢负载。 :)

编辑:我使用 from __future__ import unicode_literals 来制作 unicode 类型的字符串。我还使用 type(myString) 方法检查了它们是否真的是 unicode

我也想粘贴这个link

编辑 2:@MallikarjunaraoKosuri - 的代码有效,但在我的情况下,我在聊天机器人实例初始化中还有一件事,如下所示:

chatBot = ChatBot(
    'Test',
    trainer='chatterbot.trainers.ListTrainer',
    storage_adapter='chatterbot.storage.JsonFileStorageAdapter'
)

这是我的错误的原因。聊天机器人创建的 json 存储文件是用我的本地编码而不是 utf-8 创建的。似乎默认存储(.sqlite3)没有这个问题,所以现在我将避免使用 json 存储。但我仍然有兴趣找到解决此错误的方法。

【问题讨论】:

  • 你说字符串是 unicode 类型的:你使用的是from __future__ import unicode_literals吗?另外,哪一行会引发解码错误?因为如果字符串是 unicode,它们不应该被解码(它们都已经被解码),所以也不应该有任何解码错误。
  • 不要更改默认编码。 setdefaultencoding 因某种原因被禁用(库希望默认为 ascii)。
  • #coding 声明源文件的编码。确保以声明的编码实际保存源文件。
  • @lenz 是的,我正在使用from __future__ import unicode_literals。解码错误在train("Koliko imam še dopusta?", "Letos imate še 19 dni dopusta.") 方法中引发。
  • @MarkTolonen,好的,请注意,我将从我的代码中删除它。我在其他类似问题的stackoverflow回答中看到了这一点,并且在该线程中被标记为正确。我认为它被保存为 utf-8,我在 sublime 中做了那件事,下面的答案暗示了这一点。这就是我所说的“我还通过我的编辑器(Sublime text 3)将所有使用过的文件的编码更改为 utf-8”。但是我怎么知道在这样做之后我的文件实际上是 utf-8 编码?当我保存时,它会在程序页脚中写入一个状态,在文件的保存位置上,然后在括号中显示 utf-8。

标签: python-2.7 encoding utf-8 chatterbot


【解决方案1】:

您示例中的字符串是 not 类型的 unicode。

否则 Python 不会抛出 UnicodeDecodeError
这种类型的错误表明,在程序执行的某个步骤,Python 尝试将字节串解码为 un​​icode,但由于某种原因失败了。

在您的情况下,原因是:

  • 解码由utf-8配置
  • 您的源文件不在utf-8 中,几乎可以肯定在cp1252 中:
    import unicodedata
    
    b = '\x9a'
    
    # u = b.decode('utf-8') # UnicodeDecodeError: 'utf8' codec can't decode byte 0x9a 
                            # in position 0: invalid start byte
    
    u = b.decode('cp1252')
    
    print unicodedata.name(u) # LATIN SMALL LETTER S WITH CARON
    print u # š
    

    因此,cp1252 源中的 0x9a 字节无法使用 utf-8 解码。


    最好的解决方案是除了将您的源代码转换为 utf-8 之外什么都不做。
    使用 Sublime Text 3,您可以通过以下方式轻松完成:File -> Reopen with Encoding -> UTF-8
    但是不要忘记在转换之前 Ctrl+C 你的源代码,因为在那之后你所有的 š, č, ž 字符将被替换为?.

  • 【讨论】:

    • 我已经尝试过了,这就是我的意思:“我还通过我的编辑器(Sublime text 3)将所有使用过的文件的编码更改为 utf-8”。但我会多玩一点,我觉得这个方向可能会有一些东西。它是 unicode 类型,或者至少是 type(myString) 方法告诉我的。
    • @matiOS,你的代码中可以有 unicode 字符串,比如一些 myString,但是,例如,"Koliko imam še dopusta?",在你的 chatBot.train() 中的字符串不是 unicode蟒蛇 2.7。这是一个常规的字节串。看起来这个字节串会导致问题。此外,在UnicodeDecodeError 中提及0x9a 字节(即cp1252 中的š)始终暗示源应位于cp1252 中。您实际上是如何在 Sublime 中更改源代码的编码的?
    • 我将提到的字符串"Koliko imam še dopusta?"保存在myString变量中,然后运行type(myString)代码,结果是unicode。我明白你想告诉我什么,但似乎答案是在这个方向上。我按照您建议的方式更改了编码。
    • @matiOS,在 Python 2.7 中:myString = "Koliko imam še dopusta?"; print type(myString) 总是给出 <type 'str'>,这是一个字节字符串,而不是 unicode。尝试通过 1) CTRL+` -> 运行 Sublime 的控制台 2) 在控制台中执行 view.encoding() 来检查文件的编码
    • @matiOS,我重新创建了您的示例 - 文件内容相同,顶部为 # coding: utf-8 from __future__ import unicode_literals。如果源在cp1252 中,则抛出SyntaxError: (unicode error) 'utf8' codec can't decode byte 0x9a ...。如果我将源转换为 utf-8 一切正常。
    【解决方案2】:

    我们的一些朋友已经提出了好的部分解决方案,但我还是想将所有解决方案合二为一。

    作者@gunthercox 建议这里描述了一些指南http://chatterbot.readthedocs.io/en/stable/encoding.html#how-do-i-fix-python-encoding-errors

    # -*- coding: utf-8 -*-
    from chatterbot import ChatBot
    
    # Create a new chat bot named Test
    chatBot = ChatBot(
        'Test',
        trainer='chatterbot.trainers.ListTrainer'
    )
    
    chatBot.train([
        "Koliko imam še dopusta?",
        "Letos imate še 19 dni dopusta.",
    ])
    

    Python 终端

    >>> # -*- coding: utf-8 -*-
    ... from chatterbot import ChatBot
    >>> 
    >>> # Create a new chat bot named Test
    ... chatBot = ChatBot(
    ...     'Test',
    ...     trainer='chatterbot.trainers.ListTrainer'
    ... )
    >>> 
    >>> chatBot.train([
    ...     "Koliko imam še dopusta?",
    ...     "Letos imate še 19 dni dopusta.",
    ... ])
    List Trainer: [####################] 100%
    >>> 
    

    【讨论】:

    • 你是对的,运行上面的代码也适用于我。但是这段代码和我的原始代码有一点区别。我在初始化聊天机器人实例 storage_adapter="chatterbot.storage.JsonFileStorageAdapter" 时使用了以下行,它以我的本地编码而不是 utf-8 写入指定的数据库。有关如何解决此问题的任何建议?我将编辑我的原始问题,提供新学到的信息。
    • 它将从生产中删除,github.com/gunthercox/ChatterBot/issues/…。我建议你使用默认存储适配器sqlite3
    猜你喜欢
    • 2015-12-25
    • 2016-08-03
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多