Pandas解析错误:在将多个CSV文件读入HDF5时遇到EOF字符。

52

使用Python3,Pandas 0.12

我试图将多个csv文件(总大小为7.9 GB)写入HDF5存储器以供以后处理。每个CSV文件包含大约一百万行,15列,数据类型大部分是字符串,但有些是浮点数。然而,当我尝试读取CSV文件时,会出现以下错误:

Traceback (most recent call last):
  File "filter-1.py", line 38, in <module>
    to_hdf()
  File "filter-1.py", line 31, in to_hdf
    for chunk in reader:
  File "C:\Python33\lib\site-packages\pandas\io\parsers.py", line 578, in __iter__
    yield self.read(self.chunksize)
  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 740, in pandas.parser.TextReader._read_low_memory (pandas\parser.c:7146)
  File "parser.pyx", line 781, in pandas.parser.TextReader._read_rows (pandas\parser.c:7568)
  File "parser.pyx", line 768, in pandas.parser.TextReader._tokenize_rows (pandas\parser.c:7451)
  File "parser.pyx", line 1661, in pandas.parser.raise_parser_error (pandas\parser.c:18744)
pandas.parser.CParserError: Error tokenizing data. C error: EOF inside string starting at line 754991
Closing remaining open files: ta_store.h5... done 

编辑:

我找到了一个产生这个问题的文件。我认为它正在读取EOF字符。然而,我不知道如何解决这个问题。考虑到合并后的文件很大,检查每个字符串中的每个单个字符太麻烦了。(即使这样,我仍然不确定该怎么做。) 就我所检查的范围内,csv文件中没有奇怪的字符可以引起错误。我还尝试将error_bad_lines=False传递给pd.read_csv(),但错误仍然存在。

我的代码如下:

# -*- coding: utf-8 -*-

import pandas as pd
import os
from glob import glob


def list_files(path=os.getcwd()):
    ''' List all files in specified path '''
    list_of_files = [f for f in glob('2013-06*.csv')]
    return list_of_files


def to_hdf():
    """ Function that reads multiple csv files to HDF5 Store """
    # Defining path name
    path = 'ta_store.h5'
    # If path exists delete it such that a new instance can be created
    if os.path.exists(path):
        os.remove(path)
    # Creating HDF5 Store
    store = pd.HDFStore(path)

    # Reading csv files from list_files function
    for f in list_files():
        # Creating reader in chunks -- reduces memory load
        reader = pd.read_csv(f, chunksize=50000)
        # Looping over chunks and storing them in store file, node name 'ta_data'
        for chunk in reader:
            chunk.to_hdf(store, 'ta_data', mode='w', table=True)

    # Return store
    return store.select('ta_data')
    return 'Finished reading to HDF5 Store, continuing processing data.'

to_hdf()

编辑

如果我进入引发CParserError EOF的CSV文件,并手动删除问题行之后的所有行,那么CSV文件将被正确读取。但是我要删除的只是空白行。 奇怪的是,当我手动更正有误的csv文件时,它们可以单独加载到存储中。但是当我再次使用多个文件的列表时,“错误”的文件仍然会返回错误。


不要传递“mode ='w'”;这会在每次迭代中截断hdf文件。 - Jeff
你可以试着捕捉CParserError并跳过那个文件(在修复之前)。 - Jeff
嗨,Jeff,你认为我该如何捕获CParserError?检查每个单独的文件太麻烦了。 - Matthijs
1
首先找出它是哪个文件,不要检查,只需捕获:from pandas.io import parser; try: your read_csv look for file f except (parser.CParserError) as detail: print f, detail - Jeff
抱歉,我不太理解你的代码 - 我对Python / Pandas还比较新。你能再解释一下吗? - Matthijs
11个回答

161

我曾遇到类似的问题。在列出的代码行中,显示为 'EOF inside string' 的字符串中包含一个单引号 (')。当我添加了选项 quoting=csv.QUOTE_NONE 时,问题得到解决。

例如:

import csv
df = pd.read_csv(csvfile, header = None, delimiter="\t", quoting=csv.QUOTE_NONE, encoding='utf-8')

5
这是一个最佳解决方案。 - DACW
3
这对我有用,但如果有人能解释为什么这样做会起作用,那就太好了。 - Vikranth

31

我也遇到了同样的问题,将以下这两个参数加入我的代码后,问题消失了。

quoting=3, error_bad_lines=False 在读取csv文件时使用。


1
这个运行得非常好。有一行出现了错误。在使用上述选项执行后,我收到了以下消息:“跳过第192行:期望5个字段,但看到了74个”。 - Ayush Vatsyayan
这个问题在engine="python"的情况下让我跳过了太多行,而error_bad_lines=False只让我跳过了一行。 - Vikranth

18

我知道这是一个老问题,但我想分享更多关于这个错误根本原因的细节以及为什么@Selah的解决方案有效。

来自csv.py文档字符串:

    * quoting - controls when quotes should be generated by the writer.
    It can take on any of the following module constants:

    csv.QUOTE_MINIMAL means only when required, for example, when a
        field contains either the quotechar or the delimiter
    csv.QUOTE_ALL means that quotes are always placed around fields.
    csv.QUOTE_NONNUMERIC means that quotes are always placed around
        fields which do not parse as integers or floating point
        numbers.
    csv.QUOTE_NONE means that quotes are never placed around fields.

csv.QUOTE_MINIMAL是默认值,"是默认的quotechar。如果在您的csv文件中有一个引号字符,它将被解析为字符串,直到另一个引号字符出现为止。如果您的文件有奇数个引号字符,则最后一个引号字符在达到EOF(文件结尾)之前不会关闭。还要注意,位于引号字符之间的任何内容都将被解析为单个字符串。即使有许多换行符(预计将作为单独的行解析),也会全部进入表格的单个字段中。因此,您在错误中得到的行号可能会误导您。为了举例说明,请考虑以下内容:

In[4]: import pandas as pd
  ...: from io import StringIO
  ...: test_csv = '''a,b,c
  ...: "d,e,f
  ...: g,h,i
  ...: "m,n,o
  ...: p,q,r
  ...: s,t,u
  ...: '''
  ...: 
In[5]: test = StringIO(test_csv)
In[6]: pd.read_csv(test)
Out[6]: 
                 a  b  c
0  d,e,f\ng,h,i\nm  n  o
1                p  q  r
2                s  t  u
In[7]: test_csv_2 = '''a,b,c
  ...: "d,e,f
  ...: g,h,i
  ...: "m,n,o
  ...: "p,q,r
  ...: s,t,u
  ...: '''
  ...: test_2 = StringIO(test_csv_2)
  ...: 
In[8]: pd.read_csv(test_2)
Traceback (most recent call last):
...
...
pandas.errors.ParserError: Error tokenizing data. C error: EOF inside string starting at line 2

第一个字符串有2个(偶数)引号字符。因此,每个引号都被关闭,并且CSV被解析而没有出现错误,尽管可能不是我们预期的结果。另一个字符串有3个(奇数)引号字符。最后一个引号没有关闭,并且到达了EOF,因此出现了错误。但是,我们在错误消息中得到的第2行是误导性的。我们本应该期望得到4行,但由于第一个和第二个引号字符之间的所有内容都被解析为一个字符串,因此我们的"p,q,r行实际上是第二行。


7
使用参数 engine='python' 可以解决问题。Pandas CSV 解析器可以使用两种不同的“引擎”解析 CSV 文件,即 Python 或 C(也是默认引擎)。
pandas.read_csv(filepath, sep=',', delimiter=None, 
            header='infer', names=None, 
            index_col=None, usecols=None, squeeze=False, 
            ..., engine=None, ...)

Python引擎被描述为"速度较慢,但功能更完整",在Pandas文档中有描述。
engine : {‘c’, ‘python’}

2
这是最好的答案。同时在https://www.shanelynn.ie/pandas-csv-error-error-tokenizing-data-c-error-eof-inside-string-starting-at-line/中有详细解释。 - NellieK

6
让您的内部循环这样做将使您能够检测到“不良”文件(并进一步调查)。
from pandas.io import parser

def to_hdf():

    .....

    # Reading csv files from list_files function
    for f in list_files():
        # Creating reader in chunks -- reduces memory load

        try:

            reader = pd.read_csv(f, chunksize=50000)

            # Looping over chunks and storing them in store file, node name 'ta_data'
            for chunk in reader:
                chunk.to_hdf(store, 'ta_data', table=True)

        except (parser.CParserError) as detail:
             print f, detail

1
嗨Jeff,谢谢!它起作用了,我找到了是哪些文件/行导致了问题。现在我可以尝试手动“纠正”这些文件,但我更愿意有一个更具程序性的解决方案。因此,我需要了解实际上返回的错误是什么,以及编写什么样的代码可以自动处理该问题。 - Matthijs
你可以尝试指定一个“lineterminator”(在Linux上基本上是“\n”(或者我想在Windows上是“\n\r”))。最坏的情况是您会得到一个错误的行(因为无效终止符放在下一行中).....但需要先看看问题出在哪里:http://pandas.pydata.org/pandas-docs/dev/io.html#csv-text-files - Jeff
1
关于“glob”的问题很奇怪;我个人使用类似于“for f in os.listdir(dir); if is_ok(f): process_file(f)”这样的东西,其中“is_ok”是一个函数来接受/拒绝文件名(或者可以是其他标准或“re.search”)。 - Jeff
谢谢Jeff,我会尝试类似的方法。另外,我无法将lineterminator指定为\n\r,收到错误消息,只能使用长度为1的lineterminators(也在此处提出https://github.com/pydata/pandas/issues/3501)。 - Matthijs
2
顺便说一句,我认为代码的第一行应该是 from pandas import parser 而不是 from pandas.io import parser?因为后者无法与我的 pandas 0.15.0 版本兼容。 - Yulong
显示剩余2条评论

3

使用

engine="python",
error_bad_lines=False,

关于 read_csv 的问题。

完整的调用如下:

df = pd.read_csv(csvfile, 
                 delimiter="\t", 
                 engine="python",
                 error_bad_lines=False,  
                 encoding='utf-8')

2

我的错误:

解析错误:数据标记化出错。C 错误:字符串内部 EOF,从第 4488 行开始'

通过在代码中添加 delimiter="\t" 解决了这个问题,代码如下:

import pandas as pd
df = pd.read_csv("filename.csv", delimiter="\t")

0

在尝试从Github存储库中提取数据时遇到了类似的问题。简单的错误,是尝试从git blob(html渲染部分)而不是原始csv中提取数据。

如果您正在从git存储库中提取数据,请确保您的链接不包括\<repo name\>/blob,除非您特别关注存储库中的html代码。


0

对我来说,其他的解决方案都没有起作用,反而让我非常头痛。error_bad_lines=False仍然会出现错误C error: EOF inside string starting at line。使用不同的引号也没有达到期望的结果,因为我不想在我的文本中使用引号。

我意识到Pandas 0.20存在一个Bug。升级到版本0.21完全解决了我的问题。有关此错误的更多信息,请参见:https://github.com/pandas-dev/pandas/issues/16559

注意:如URL中所述,这可能与Windows相关。


1
这个不起作用 - 即使升级到 pandas-0.22.0,我仍然收到同样的错误。 - Ayush Vatsyayan

0

经过数小时的寻找解决方案,我终于想出了一个解决方法。

消除这个 C error: EOF inside string starting at line exception 的最佳方法是预处理输入数据(如果有这样的机会),而不会降低多进程效率。

将输入文件中所有的 '\n' 条目替换为例如 ', ' 或任何其他唯一的符号序列(例如 'aghr21*&')。然后您就可以将数据读入您的 dataframe 中。

在读取数据之后,您可能希望将所有唯一的符号序列('aghr21*&')替换回 '\n'。


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