在 Pandas 中读取 CSV 文件时出现 UnicodeDecodeError

UnicodeDecodeError when reading CSV file in Pandas

提问人:TravisVOX 提问时间:8/11/2013 最后编辑:Trenton McKinneyTravisVOX 更新时间:10/30/2023 访问量:972736

问:

我正在运行一个程序,该程序正在处理 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

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

python pandas csv 数据帧 unicode

评论


答:

1199赞 Stefan 8/11/2013 #1

read_csv选择处理不同格式的文件。我主要使用 ,或者用于阅读,通常用于 .encodingread_csv('file', encoding = "ISO-8859-1")encoding = "utf-8"utf-8to_csv

您也可以使用几个选项之一,例如 or (Windows) 代替(请参阅 python 文档,以及您可能遇到的许多其他编码)。alias'latin''cp1252''ISO-8859-1'

请参阅相关的 Pandas 文档、csv 文件的 python 文档示例,以及 SO 上的大量相关问题。一个好的背景资源是每个开发人员都应该了解的有关 unicode 和字符集的知识

要检测编码(假设文件包含非 ASCII 字符),可以使用(请参见手册页)或 (linux) 或 (osx)(请参见手册页)。encafile -ifile -I

评论

11赞 Stefan 6/14/2019
@Ben 这是一个很好的资源:每个开发人员都应该了解的有关 unicode 和字符集的知识
1赞 tripleee 4/7/2022
ISO-8859-1 在 Python 编码中具有独特的属性,它可以绝对读取任何二进制数据而不会引发错误。很多时候,初学者会尝试不同的编码,而没有实际查看他们的结果数据,然后想知道为什么当他们选择了错误的编码时,他们的结果会是垃圾。
0赞 Karl Knechtel 8/18/2022
@tripleee没有“Python 编码”(除非您将实现 ROT-13 之类的东西视为 Python 系统中的“编码”);ISO-8859-1 是国际公认的标准(因此是 ISO),在无数环境中实施了无数次。16 个 ISO-8859 编码中有 10 个可以处理任意二进制文件,几个历史 DOS 代码页、旧版 Macintosh 文本编码和其他一些代码也可以处理。不过,ISO-8859-1 确实具有(必然)独特的属性,即它按顺序将这些字节映射到前 256 个 Unicode 码位。
0赞 tripleee 8/18/2022
当然,我的意思是 Python 支持的字符编码。
208赞 Gil Baggio 12/21/2017 #2

最简单的解决方案:

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

备选解决方案:

崇高的文字:

  • Sublime 文本编辑器VS Code 中打开 csv 文件。
  • 以 utf-8 格式保存文件。
  • 在崇高中,单击文件 -> 使用编码保存 -> UTF-8

VS 代码:

在 VSCode 的底部栏中,您会看到标签 UTF-8。单击它。将打开一个弹出窗口。单击“使用编码保存”。现在,您可以为该文件选择新的编码。

然后,您可以像往常一样读取文件:

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

其他不同的编码类型包括:

encoding = "cp1252"
encoding = "ISO-8859-1"
5赞 J. Ternent 5/14/2018 #3

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

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

43赞 Serge Ballesta 8/9/2018 #4

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. 您不想为编码问题而烦恼,而只想加载该死的文件,无论某些文本字段是否包含垃圾。好的,您只需要使用编码,因为它接受任何可能的字节作为输入(并将其转换为相同代码的 unicode 字符):Latin1

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

    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, ...)
    
24赞 bhavesh 12/15/2018 #5
with open('filename.csv') as f:
   print(f)

执行此代码后,您将找到“文件名.csv”的编码,然后执行如下代码

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

给你

2赞 nbwoodward 12/18/2018 #6

这个答案似乎是 CSV 编码问题的包罗万象。如果您的标头遇到奇怪的编码问题,如下所示:

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

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

Python 读取 csv - 嵌入到第一个键中的 BOM

解决方案是加载 CSV:encoding="utf-8-sig"

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

希望这对某人有所帮助。

7赞 Vodyanikov Andrew 12/18/2018 #7

就我而言,根据 Notepad++ 的说法,文件具有编码功能。 它是针对 python 的。USC-2 LE BOMencoding="utf_16_le"

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

2赞 tshirtdr1 1/1/2019 #8

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

希望这对某人有所帮助。

评论

0赞 tshirtdr1 1/1/2019
Nisse,感谢您的编辑。你能解释一下你改变了什么吗?我看不出有什么区别。
0赞 tripleee 4/22/2022
我不是 Nisse,但他在“希望这有帮助”结尾之前添加了一个句号和一个换行符。
6赞 Jan33 1/31/2019 #9

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

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

评论

0赞 Sean McCarthy 8/12/2019
这也对我有用。编码 = “ISO-8859-1” 也是如此。这绝对是一个编码问题。如果特殊字符以 ANSI 编码,例如椭圆字符(即“...”),并且您尝试以 UTF-8 读取它,则可能会出现错误。最重要的是,您必须知道创建文件的编码。
0赞 tripleee 4/23/2022
“以 ANSI 编码”的定义不明确。Windows 上的 ANSI 术语用词不当,没有命名任何特定的编码;相反,它选择在系统设置中其他位置定义的编码。
1赞 Himanshu Sharma 5/13/2019 #10

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

6赞 Victor Villacorta 7/26/2019 #11

就我而言,这适用于 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) 
1赞 Ke Xu 10/8/2019 #12

试试这个:

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

看起来它会处理编码,而无需通过参数显式表达它

评论

0赞 Fjurg 10/4/2022
我不确定为什么这与仅仅使用不同,但它确实有效。data = pd.read_csv(f)
1赞 DaveP 10/11/2019 #13

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

with open(path, 'r') as f:
    encoding = f.encoding 

df = pd.read_csv(path,sep=sep, encoding=encoding)

在 python 3.7 中

评论

0赞 tripleee 4/22/2022
如果 Python 无法对编码进行神圣化,这将更早失败。在非 Windows 平台上的现代 Python 3 上,这将默认为 UTF-8,如果文件不兼容,则失败。在 Windows 上,这将默认为系统配置为默认的任何内容,因此如果您幸运的话,它可能会起作用,或者如果您不太幸运,它可能会产生垃圾。
4赞 Jon 10/23/2019 #14

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

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

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

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

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

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

选项 3:解决方案是我个人的首选解决方案。使用 vanilla 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)

希望这可以帮助第一次遇到此问题的人。

评论

0赞 tripleee 4/22/2022
在这种情况下,正确的解决方案是建立正确的编码。基于单个字符,很难权威地说,但0xF1对应于例如拉丁语 1 中的 ñtripleee.github.io/8bit/#f1 列出了此字节在 Python 支持的所有 8 位编码中表示的字符。 如果您关心数据的完整性,这是一个非常糟糕的主意。errors="ignore"
0赞 Jon 4/26/2022
@tripleee好主意,但这是一个并不总是可用的解决方案。有时,您会得到一个数据集,对如何导出它有很大的发言权
0赞 tripleee 4/26/2022
我看不出你的评论有什么意义。如果您可以自己以已知编码导出文件,那么当然不需要弄清楚编码。如果你得到一个编码未知的文件,弄清楚它采用哪种编码比盲目猜测或粗暴地删除任何非 UTF-8 的数据要好得多。这仍然假设文件没有损坏或其他东西,在这种情况下,除了找出正确的编码,您还需要手动查找并修复损坏。
3赞 Luk Aron 11/3/2019 #15

我无法打开从网上银行下载的简体中文 CSV 文件, 我试过了,我试过了,我试过了,都无济于事。latin1iso-8859-1cp1252

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

评论

0赞 tripleee 4/22/2022
您尝试的任何编码都不支持表示中文文本。GBK在中国仍然适度流行,它是国家标准,但在其他任何地方都很少使用。参见 en.wikipedia.org/wiki/GBK_(character_encoding)
4赞 Mujeeb Ishaque 4/22/2020 #16

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

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

^此行导致相同的错误,因为我正在使用方法读取 excel 文件。用于读取 .xlxsread_csv()read_excel()

评论

0赞 Mujeeb Ishaque 4/22/2020
哇,其他人都在谈论编码问题。看起来我的问题很奇怪。
26赞 Prakhar Rathi 5/21/2020 #17

请尝试添加

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

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

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

3赞 Dileep Dominic 6/14/2020 #18

你可以试试这个。

import csv
import pandas as pd
df = pd.read_csv(filepath,encoding='unicode_escape')
-1赞 ah bon 7/7/2020 #19

您可以尝试:

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

13赞 Kunal Kumar 7/8/2020 #20

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

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

1赞 Om Rastogi 10/4/2020 #21

有时问题仅出在 .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 

评论

0赞 Arpad Horvath -- Слава Україні 10/4/2020
不确定您在此处使用哪个程序。胜过?
0赞 Om Rastogi 10/4/2020
打开EXCEL文件
0赞 tripleee 4/22/2022
这假设 CSV 是从 Excel 文件生成的,但显然情况并非如此(如果是这样,也许您应该批判性地检查您的工具选择)。
0赞 Om Rastogi 4/22/2022
你是对的,但无论使用什么工具创建CSV文件,MS excel都支持打开CSV文件,因此您可以使用它。此外,大多数情况下,CSV 文件仅由 excel 工具生成。如果这不起作用,您可以尝试使用其他源工具。
33赞 Fledias weh 2/5/2021 #22

对于所述问题,这是一种更通用的脚本方法。

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 标准编码)。 此处提供了不同 python 版本的标准编码的可用 python 列表: 有用的堆栈溢出答案

在一小块数据上尝试每种编码; 仅打印工作编码。 输出是显而易见的。 此输出还解决了一个问题,即像“latin1”这样的编码在出现任何错误时都不一定会产生所需的结果。

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

评论

0赞 Egbert Ke 8/4/2023
哈哈,干得好兄弟。
-1赞 Reza Rahimi 5/27/2021 #23

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

0赞 Onur Kirman 12/28/2021 #24

就我而言,我无法使用之前提供的任何方法克服此问题。以某种方式将编码器类型更改为 、 、 或任何其他类型都不起作用。utf-8utf-16iso-8859-1

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

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

事情似乎运作良好。

12赞 mikey 3/2/2022 #25

您始终可以尝试先检测文件的编码,使用 或 或:chardetcchardetcharset-normalizer

from pathlib import Path
import chardet

filename = "file_name.csv"
detected = chardet.detect(Path(filename).read_bytes())
# detected is something like {'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}

encoding = detected.get("encoding")
assert encoding, "Unable to detect encoding, is it a binary file?"

df = pd.read_csv(filename, encoding=encoding)

0赞 Khalid Abdalgader 9/8/2023 #26

只需将编码添加到您的方法中,如下所示:

import pandas as pd

df = pd.read_csv('sales_data_sample.csv', encoding = "ISO-8859-1")

print(df)

评论

0赞 ouroboros1 9/10/2023
嗨,哈立德,这只是已接受答案的简化版(信息量较少)。除非您有任何实质性的内容要添加到该解决方案中,以使答案脱颖而出,否则请考虑删除此答案,并且不要不必要地使帖子混乱。另外,为了将来参考:请在您的答案中添加解释性注释。也就是说:解释为什么建议的方法可以解决问题,以便 SO 用户可以从中学习。
0赞 Ryabchenko Alexander 10/30/2023 #27

再多一张收据

   import csv
   import chardet
   import pandas

   # io_bytes: BytesIO  <=> input data 

   byte_line: bytes = io_bytes.readline()
   dialect = csv.Sniffer().sniff(str(byte_line))
   encoding_info = chardet.detect(byte_line)
   io_bytes.seek(0)
   dataframe = pandas.read_csv(
       io_bytes, 
       delimiter=dialect.delimiter, 
       encoding=encoding_info["encoding"],
   )