【问题标题】:UnicodeDecodeError when reading CSV file in Pandas with Python使用 Python 在 Pandas 中读取 CSV 文件时出现 UnicodeDecodeError
【发布时间】:2013-08-12 20:44:37
【问题描述】:

我正在运行一个正在处理 30,000 个类似文件的程序。它们中的随机数正在停止并产生此错误...

File "C:\Importer\src\dfman\importer.py", line 26, in import_chr
     data = pd.read_csv(filepath, names=fields)
File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 400, in parser_f
     return _read(filepath_or_buffer, kwds)
File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 205, in _read
     return parser.read()
   File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 608, in read
     ret = self._engine.read(nrows)
File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 1028, in read
     data = self._reader.read(nrows)
File "parser.pyx", line 706, in pandas.parser.TextReader.read (pandas\parser.c:6745)
File "parser.pyx", line 728, in pandas.parser.TextReader._read_low_memory (pandas\parser.c:6964)
File "parser.pyx", line 804, in pandas.parser.TextReader._read_rows (pandas\parser.c:7780)
File "parser.pyx", line 890, in pandas.parser.TextReader._convert_column_data (pandas\parser.c:8793)
File "parser.pyx", line 950, in pandas.parser.TextReader._convert_tokens (pandas\parser.c:9484)
File "parser.pyx", line 1026, in pandas.parser.TextReader._convert_with_dtype (pandas\parser.c:10642)
File "parser.pyx", line 1046, in pandas.parser.TextReader._string_convert (pandas\parser.c:10853)
File "parser.pyx", line 1278, in pandas.parser._string_box_utf8 (pandas\parser.c:15657)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xda in position 6: invalid    continuation byte

这些文件的来源/创建都来自同一个地方。纠正此问题以继续导入的最佳方法是什么?

【问题讨论】:

  • 添加这个参数对我有用:encoding_errors='ignore'

标签: python pandas csv dataframe unicode


【解决方案1】:

read_csv 采用encoding 选项来处理不同格式的文件。我主要使用read_csv('file', encoding = "ISO-8859-1"),或者encoding = "utf-8" 用于阅读,一般utf-8 用于to_csv

您也可以使用多个alias 选项之一,例如'latin''cp1252' (Windows),而不是'ISO-8859-1'(请参阅python docs,也可以使用您可能遇到的许多其他编码)。

relevant Pandas documentation, python docs examples on csv files,还有很多关于 SO 的相关问题。一个好的后台资源是What every developer should know about unicode and character sets

要检测编码(假设文件包含非ASCII字符),您可以使用enca(参见man page)或file -i(linux)或file -I(osx)(参见man page) .

【讨论】:

  • 由于这是一个 Windows 问题,cp1252 可能比 iso-8859-1 更可取。
  • 感谢pd.read_csv('immigration.csv', encoding = "ISO-8859-1", engine='python')为我工作
  • 不要仅仅因为没有抛出异常就盲目地假设某种编码是正确的。您需要查看字符串并确定解释是否有意义。例如,如果您获得的是“hors d’½uvre”而不是“hors d’œuvre”,您可能需要从 ISO-8859-1 切换到 ISO-8859-15。
  • 对我来说编码是ANSI。为了弄清楚,我在notepad中打开了csv,然后点击save as,它在保存按钮旁边显示了编码。
【解决方案2】:

就我而言,我无法使用之前提供的任何方法来解决这个问题。将编码器类型更改为 utf-8utf-16iso-8859-1 或任何其他类型都不起作用。

但是我没有使用pd.read_csv(filename, delimiter=';'),而是使用了;

pd.read_csv(open(filename, 'r'), delimiter=';')

一切似乎都很好。

【讨论】:

    【解决方案3】:

    Pandas 不会通过更改编码样式来自动替换有问题的字节。就我而言,将编码参数从encoding = "utf-8" 更改为encoding = "utf-16" 解决了这个问题。

    【讨论】:

      【解决方案4】:

      这是针对所述问题的更通用的脚本方法。

      import pandas as pd
      
      encoding_list = ['ascii', 'big5', 'big5hkscs', 'cp037', 'cp273', 'cp424', 'cp437', 'cp500', 'cp720', 'cp737'
                       , 'cp775', 'cp850', 'cp852', 'cp855', 'cp856', 'cp857', 'cp858', 'cp860', 'cp861', 'cp862'
                       , 'cp863', 'cp864', 'cp865', 'cp866', 'cp869', 'cp874', 'cp875', 'cp932', 'cp949', 'cp950'
                       , 'cp1006', 'cp1026', 'cp1125', 'cp1140', 'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254'
                       , 'cp1255', 'cp1256', 'cp1257', 'cp1258', 'euc_jp', 'euc_jis_2004', 'euc_jisx0213', 'euc_kr'
                       , 'gb2312', 'gbk', 'gb18030', 'hz', 'iso2022_jp', 'iso2022_jp_1', 'iso2022_jp_2'
                       , 'iso2022_jp_2004', 'iso2022_jp_3', 'iso2022_jp_ext', 'iso2022_kr', 'latin_1', 'iso8859_2'
                       , 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', 'iso8859_7', 'iso8859_8', 'iso8859_9'
                       , 'iso8859_10', 'iso8859_11', 'iso8859_13', 'iso8859_14', 'iso8859_15', 'iso8859_16', 'johab'
                       , 'koi8_r', 'koi8_t', 'koi8_u', 'kz1048', 'mac_cyrillic', 'mac_greek', 'mac_iceland', 'mac_latin2'
                       , 'mac_roman', 'mac_turkish', 'ptcp154', 'shift_jis', 'shift_jis_2004', 'shift_jisx0213', 'utf_32'
                       , 'utf_32_be', 'utf_32_le', 'utf_16', 'utf_16_be', 'utf_16_le', 'utf_7', 'utf_8', 'utf_8_sig']
      
      for encoding in encoding_list:
          worked = True
          try:
              df = pd.read_csv(path, encoding=encoding, nrows=5)
          except:
              worked = False
          if worked:
              print(encoding, ':\n', df.head())
      

      一个从可用于 python 版本的所有标准编码开始(在本例中为 3.7 python 3.7 standard encodings)。 此处提供了不同 python 版本的标准编码的可用 python 列表:Helpful Stack overflow answer

      在一小块数据上尝试每种编码; 只打印工作编码。 输出直接明显。 此输出还解决了这样的问题:像“latin1”这样的编码可能会出现任何错误,但不一定会产生想要的结果。

      如果遇到问题,我会尝试针对有问题的CSV 文件使用这种方法,然后可能会尝试将找到的工作编码用于所有其他文件。

      【讨论】:

        【解决方案5】:

        有时问题仅出在 .csv 文件上。该文件可能已损坏。 遇到这个问题的时候。再次将文件“另存为”为 csv。

        0. Open the xls/csv file
        1. Go to -> files 
        2. Click -> Save As 
        3. Write the file name 
        4. Choose 'file type' as -> CSV [very important]
        5. Click -> Ok 
        

        【讨论】:

        • 不确定您在这里使用哪个程序。 Excel?
        • 打开excel文件
        【解决方案6】:

        最简单的解决方案:

        import pandas as pd
        df = pd.read_csv('file_name.csv', engine='python')
        

        替代方案:

        • Sublime 文本编辑器VS Code 中打开 csv 文件。
        • 以 utf-8 格式保存文件。

        在 sublime 中,点击 File -> Save with encoding -> UTF-8

        然后,您可以照常读取文件:

        import pandas as pd
        data = pd.read_csv('file_name.csv', encoding='utf-8')
        

        其他不同的编码类型是:

        encoding = "cp1252"
        encoding = "ISO-8859-1"
        

        【讨论】:

        • 问题解释说有 30,000 个这样的文件。手动打开每个文件是不切实际的。
        • 至少对于一个文件,这似乎对我有用!
        • C 引擎显然更宽容地接受它。对于使用encoding='iso-8859-1' 可以正常打开的特定CSV 文件,使用engine='python' 会抛出_csv.Error: field larger than field limit (131072)
        • 使用 save 和编码的替代解决方案真的很有帮助!这是 VSCode 的使用方法stackoverflow.com/questions/30082741/…
        • 感谢您的提示,通过 VS Code 保存 CSV 文件对我有用。
        【解决方案7】:

        尝试更改编码。 就我而言,encoding = "utf-16" 有效。

        df = pd.read_csv("file.csv",encoding='utf-16')

        【讨论】:

        • with open (file) as f: encoding = f.encoding 为我正在使用的文件返回了cp1252。但是,指定 encoding = 'utf-16' 是为我打开文件而没有任何错误的原因。另外,我设置了engine = 'python'。感谢您的建议。
        • utf-16 为我工作!以上所有情况 - 没有(
        【解决方案8】:

        你可以试试:

        df = pd.read_csv('./file_name.csv', encoding='gbk')

        【讨论】:

          【解决方案9】:

          你可以试试这个。

          import csv
          import pandas as pd
          df = pd.read_csv(filepath,encoding='unicode_escape')
          

          【讨论】:

            【解决方案10】:

            请尝试添加

            encoding='unicode_escape'
            

            这会有所帮助。为我工作。此外,请确保您使用了正确的分隔符和列名。

            您可以从仅加载 1000 行开始快速加载文件。

            【讨论】:

              【解决方案11】:

              我遇到的另一个导致相同错误的重要问题是:

              _values = pd.read_csv("C:\Users\Mujeeb\Desktop\file.xlxs")
              

              ^这行导致了同样的错误,因为我正在使用read_csv() 方法读取一个excel文件。使用read_excel() 读取.xlxs

              【讨论】:

              • 哇,其他人都在谈论编码问题。看起来我的问题很奇怪。
              【解决方案12】:

              在我的例子中,根据 Notepad++,一个文件具有USC-2 LE BOM 编码。 对于 python,它是 encoding="utf_16_le"

              希望,这有助于更快地为某人找到答案。

              【讨论】:

                【解决方案13】:

                我发布答案是为了提供更新的解决方案并解释为什么会出现此问题。假设您从数据库或 Excel 工作簿中获取此数据。如果您有像La Cañada Flintridge city 这样的特殊字符,那么除非您使用UTF-8 编码导出数据,否则您将引入错误。 La Cañada Flintridge city 将变为 La Ca\xf1ada Flintridge city。如果您使用pandas.read_csv 而不对默认参数进行任何调整,您将遇到以下错误

                UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf1 in position 5: invalid continuation byte
                

                幸运的是,有一些解决方案。

                选项 1,修复导出。请务必使用UTF-8 编码。

                选项2,如果您无法修复导出问题,并且需要使用pandas.read_csv,请务必包含以下参数,engine='python'。默认情况下,pandas 使用engine='C',它非常适合读取大型干净文件,但如果出现任何意外情况会崩溃。以我的经验,设置encoding='utf-8' 从未修复过这个UnicodeDecodeError。此外,您不需要使用errors_bad_lines,但是,如果您真的需要它,这仍然是一个选项。

                pd.read_csv(<your file>, engine='python')
                

                选项 3: 解决方案是我个人的首选解决方案。使用普通 Python 读取文件。

                import pandas as pd
                
                data = []
                
                with open(<your file>, "rb") as myfile:
                    # read the header seperately
                    # decode it as 'utf-8', remove any special characters, and split it on the comma (or deliminator)
                    header = myfile.readline().decode('utf-8').replace('\r\n', '').split(',')
                    # read the rest of the data
                    for line in myfile:
                        row = line.decode('utf-8', errors='ignore').replace('\r\n', '').split(',')
                        data.append(row)
                
                # save the data as a dataframe
                df = pd.DataFrame(data=data, columns = header)
                

                希望这对第一次遇到此问题的人有所帮助。

                【讨论】:

                  【解决方案14】:

                  我无法打开从网上银行下载的简体中文 CSV 文件, 我试过latin1,我试过iso-8859-1,我试过cp1252,都没有用。

                  但是 pd.read_csv("",encoding ='gbk') 只是完成了这项工作。

                  【讨论】:

                    【解决方案15】:

                    在传递给 pandas 之前检查编码。它会减慢你的速度,但是......

                    with open(path, 'r') as f:
                        encoding = f.encoding 
                    
                    df = pd.read_csv(path,sep=sep, encoding=encoding)
                    

                    在 python 3.7 中

                    【讨论】:

                      【解决方案16】:

                      试试这个:

                      import pandas as pd
                      with open('filename.csv') as f:
                          data = pd.read_csv(f)
                      

                      看起来它会处理编码而不通过参数明确表达它

                      【讨论】:

                        【解决方案17】:

                        为此苦苦挣扎了一段时间,并认为我会在这个问题上发帖,因为它是第一个搜索结果。将encoding="iso-8859-1" 标签添加到pandas read_csv 不起作用,任何其他编码也不起作用,不断给出UnicodeDecodeError。

                        如果您将文件句柄传递给pd.read_csv(),,则需要将encoding 属性放在打开的文件上,而不是放在read_csv 中。事后看来很明显,但要追查一个微妙的错误。

                        【讨论】:

                          【解决方案18】:

                          在我的情况下,这适用于 python 2.7:

                          data = read_csv(filename, encoding = "ISO-8859-1", dtype={'name_of_colum': unicode}, low_memory=False) 
                          

                          对于 python 3,仅:

                          data = read_csv(filename, encoding = "ISO-8859-1", low_memory=False) 
                          

                          【讨论】:

                            【解决方案19】:

                            我正在使用 Jupyter 笔记本。就我而言,它以错误的格式显示文件。 “编码”选项不起作用。 所以我将 csv 保存为 utf-8 格式,它可以工作。

                            【讨论】:

                              【解决方案20】:

                              尝试指定 engine='python'。 它对我有用,但我仍在试图找出原因。

                              df = pd.read_csv(input_file_path,...engine='python')
                              

                              【讨论】:

                              • 这也对我有用。编码=“ISO-8859-1”也是如此。这绝对是一个编码问题。如果使用 ANSI 编码的特殊字符,例如椭圆字符(即“...”),并且您尝试以 UTF-8 读取它,则可能会出错。底线是您必须知道创建文件时使用的编码。
                              【解决方案21】:

                              我正在发布对这个旧线程的更新。我找到了一种可行的解决方案,但需要打开每个文件。我在 LibreOffice 中打开了我的 csv 文件,选择了另存为 > 编辑过滤器设置。在下拉菜单中,我选择了 UTF8 编码。然后我将encoding="utf-8-sig" 添加到data = pd.read_csv(r'C:\fullpathtofile\filename.csv', sep = ',', encoding="utf-8-sig")

                              希望这对某人有所帮助。

                              【讨论】:

                              • Nisse,感谢您的编辑。你能解释一下你改变了什么吗?我看不出有什么不同。
                              【解决方案22】:

                              这个答案似乎是 CSV 编码问题的全部。如果您的标头出现奇怪的编码问题,如下所示:

                              >>> f = open(filename,"r")
                              >>> reader = DictReader(f)
                              >>> next(reader)
                              OrderedDict([('\ufeffid', '1'), ... ])
                              

                              然后,您的 CSV 文件开头有一个字节顺序标记 (BOM) 字符。这个答案解决了这个问题:

                              Python read csv - BOM embedded into the first key

                              解决办法是用encoding="utf-8-sig"加载CSV:

                              >>> f = open(filename,"r", encoding="utf-8-sig")
                              >>> reader = DictReader(f)
                              >>> next(reader)
                              OrderedDict([('id', '1'), ... ])
                              

                              希望这对某人有所帮助。

                              【讨论】:

                                【解决方案23】:
                                with open('filename.csv') as f:
                                   print(f)
                                

                                执行此代码后,您会发现 'filename.csv' 的编码,然后执行以下代码

                                data=pd.read_csv('filename.csv', encoding="encoding as you found earlier"
                                

                                你来了

                                【讨论】:

                                  【解决方案24】:

                                  Pandas 允许指定编码,但不允许忽略错误以自动替换有问题的字节。因此,没有一刀切的方法,而是根据实际用例采用不同的方法。

                                  1. 您知道编码,并且文件中没有编码错误。 太好了:您只需指定编码:

                                    file_encoding = 'cp1252'        # set file_encoding to the file encoding (utf8, latin1, etc.)
                                    pd.read_csv(input_file_and_path, ..., encoding=file_encoding)
                                    
                                  2. 你不想被编码问题所困扰,只想加载那个该死的文件,不管某些文本字段是否包含垃圾。好的,您只需要使用Latin1 编码,因为它接受任何可能的字节作为输入(并将其转换为相同代码的 unicode 字符):

                                    pd.read_csv(input_file_and_path, ..., encoding='latin1')
                                    
                                  3. 您知道大部分文件都是使用特定编码编写的,但它也包含编码错误。一个真实的例子是一个 UTF8 文件,该文件已使用非 utf8 编辑器进行编辑,其中包含一些具有不同编码的行。 Pandas 没有提供特殊的错误处理,但 Python open 函数有(假设是 Python3),并且read_csv 接受文件之类的对象。这里使用的典型错误参数是'ignore',它只是抑制违规字节或(恕我直言)'backslashreplace',它用 Python 的反斜杠转义序列替换违规字节:

                                    file_encoding = 'utf8'        # set file_encoding to the file encoding (utf8, latin1, etc.)
                                    input_fd = open(input_file_and_path, encoding=file_encoding, errors = 'backslashreplace')
                                    pd.read_csv(input_fd, ...)
                                    

                                  【讨论】:

                                  猜你喜欢
                                  • 2018-12-26
                                  • 2020-10-07
                                  • 2020-01-29
                                  • 2018-10-24
                                  相关资源
                                  最近更新 更多