UnicodeEncodeError: 'ascii'编解码器无法在位置32处对字符u'\u2013'进行编码:该序数不在范围内(128)。

78
我正在使用xlrd解析一个XSL文件,大部分功能都正常。我有一个字典,其中键是字符串,值是字符串列表。所有的键和值都是Unicode编码的。我可以使用str()方法打印出大多数的键和值,但是一些值包含Unicode字符\u2013,因此我遇到上述错误。我怀疑这是因为Unicode嵌入在Unicode中,Python解释器无法解码。那么我该如何消除这个错误呢?
8个回答

83
您可以直接打印Unicode对象,不需要将其转换为str()。
假设您确实需要一个str:
当您执行str(u'\u2013')时,您正在尝试将Unicode字符串转换为8位字符串。为此,您需要使用编码(一种Unicode数据到8位数据的映射)。str()使用系统默认编码,而Python 2下的默认编码是ASCII。 ASCII仅包含Unicode的前127个代码点,即\u0000到\u007F1。结果就是你会得到上面的错误提示,因为ASCII编解码器不知道\u2013表示什么(顺便说一下,它是一个长破折号)。
因此,您需要指定要使用的编码方式。常见的编码方式有ISO-8859-1,通常称为Latin-1,它包含了前256个代码点;UTF-8,它可以通过使用可变长度编码来编码所有代码点;在Windows上常见的CP1252以及各种中文和日文编码方式。
使用方法如下:
u'\u2013'.encode('utf8')

结果是一个包含字节序列的str,这个字节序列是所讨论字符的UTF8表示形式:

'\xe2\x80\x93'

你可以将它打印出来:

>>> print '\xe2\x80\x93'
–

这非常全面。谢谢。我有一个问题 - 假设是Twitter流,您不会事先知道编码方式。您会如何处理? - karthikr
@karthikr:我很难相信Twitter不提供编码。 - Lennart Regebro

29
您也可以尝试这个来获取文本。
foo.encode('ascii', 'ignore')

1
在进行了许多SO搜索后,我终于解决了这个问题。我的特定用法是在打印时出现的,因为Windows和Linux都会抛出这个编码错误。 - ddisqq
这将会丢失任何非ASCII字符的数据,正确的方法是使用正确的编码进行编码。 - Padraic Cunningham
这将忽略非ASCII字符。你的答案就是忽略这个问题吗? - John Strood
如果您没有使用非ASCII字符,那么是的。 - Bilbo Baggins

7

在这里,str(u'\u2013')会导致错误,因此使用isinstance(foo,basestring)来检查unicode/string的类型,如果不是basestring类型,则将其转换为Unicode,然后再应用编码。

if isinstance(foo,basestring):
    foo.encode('utf8')
else:
    unicode(foo).encode('utf8')

further read


5

我有同样的问题。这对我来说很有效:

str(objdata).encode('utf-8')

2
我最近在一个项目中遇到了这个问题,真的很烦人。我最终发现这是因为我们在 Docker 中使用的 Python 的编码方式是 "ansi_x3.4-1968" 而不是 "utf-8"。所以如果有人正在使用 Docker 并遇到此错误,则按照以下步骤可能会彻底解决您的问题。
1. 在 Dockerfile 相同的目录下创建一个名为 default_locale 的文件,并将以下行放入其中: environment=LANG="es_ES.utf8", LC_ALL="es_ES.UTF-8", LC_LANG="es_ES.UTF-8"
2. 将以下内容添加到 Dockerfile 中: RUN apt-get clean && apt-get update && apt-get install -y locales RUN locale-gen en_CA.UTF-8 COPY ./default_locale /etc/default/locale RUN chmod 0755 /etc/default/locale ENV LC_ALL=en_CA.UTF-8 ENV LANG=en_CA.UTF-8 ENV LANGUAGE=en_CA.UTF-8
当我重新构建和运行我的 Docker 时,这些步骤彻底解决了我的问题,希望这也能解决您的问题。

0

首先在此链接https://unicode-table.com/en/2013/中找出Unicode字符。

然后在代码中使用以下内容:

{your-string-variable}.replace(u"\u2013", "-")

同样适用于所有出现错误的Unicode。

0

在使用openpyxl读取Excel文件时,我遇到了同样的错误,于是我选择编写一个函数来帮助我删除任何非ASCII字符,同时保留换行符。

def clean_string(b_string):
    # Decode bytes object to string and remove non-ASCII characters except newlines
    cleaned_string = ''
    for byte in b_string:
        if byte == ord('\n') or byte < 128:
            cleaned_string += chr(byte)
    return cleaned_string

它的使用方式如下:

def upload_conditions(request):
    # Condition.objects.all().delete()
    if request.method == 'POST':
        excel_file = request.FILES.get("nfile")
        wb = openpyxl.load_workbook(excel_file)
        excel_data = list()

        for letter in ["A"]:
            worksheet = wb[letter]
            for row in worksheet.iter_rows():
                row_data = list()
                for cell in row:
                    value = cell.value
                    if value:
                        encoded_string = str(value).encode('utf-8', 'ignore')
                        row_data.append(clean_string(encoded_string))
                        
                    else:
                        row_data.append("")
                    
                excel_data.append(row_data)

在编程中,调用clean_string函数可以快速清理带有非ASCII字符的b_string或字符串。

要对字符串进行编码,我是这样做的:

'''
value - a string to encode with ascii like this one - b'Legionnaires\xe2\x80\x99 disease\nwith newline'
'''
encoded_string = str(value).encode('utf-8', 'ignore')

0

对我来说这个有效

unicode(data).encode('utf-8')


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