【问题标题】:_csv.Error: field larger than field limit (131072)_csv.Error:字段大于字段限制 (131072)
【发布时间】:2013-02-10 10:01:21
【问题描述】:

我在一个包含非常大字段的 csv 文件中读取了一个脚本:

# example from http://docs.python.org/3.3/library/csv.html?highlight=csv%20dictreader#examples
import csv
with open('some.csv', newline='') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

但是,这会在某些 csv 文件上引发以下错误:

_csv.Error: field larger than field limit (131072)

如何分析包含大字段的 csv 文件?跳过包含大量字段的行不是一种选择,因为需要在后续步骤中分析数据。

【问题讨论】:

  • 更好的是考虑为什么有这么大的字段您的数据中是否有预期?有时,像这样的错误表明存在不同的问题。我有一些包含随机双引号字符的错误数据,因此必须使用此处另一个答案中显示的 QUOTE_NONE 选项。
  • 我更新了我的问题以表明在我的情况下可能会出现巨大的字段。 csv文件中没有坏数据。
  • @dustmachine 之所以会发生这种情况,是因为有时您会发现有人在数据库表中以 base64 格式存储图像(或其他二进制文件)。

标签: python csv


【解决方案1】:

.csv 字段大小通过 [Python 3.Docs]: csv.field_size_limit([new_limit]) 控制(强调是我的):

返回解析器允许的当前最大字段大小。 如果给出 new_limit,这将成为新的限制

默认设置为 1310720x20000 (128k) ,对于任何体面的 .csv 来说应该足够了:

>>> import csv
>>>
>>>
>>> limit0 = csv.field_size_limit()
>>> limit0
131072
>>> "0x{0:016X}".format(limit0)
'0x0000000000020000'

但是,当处理一个 .csv 文件(使用正确的引用和分隔符)时,(至少)一个字段长于这个大小,错误会弹出.
为了消除错误,应该增加大小限制(为避免任何担忧,尝试最大可能值)。

在幕后(查看[GitHub]: python/cpython - (master) cpython/Modules/_csv.c了解实现细节),保存这个值的变量是一个C long[Wikipedia]: C data types),其大小CPU 架构和 OS (ILP) 而异。经典的区别:对于 64bit OS(和 Python 构建),long 类型大小(以位为单位)为:

  • 尼克斯64
  • 32

当试图设置它时,新值被检查为在 long 边界内,这就是为什么在某些情况下会弹出另一个异常(因为 sys.maxsize 是通常 64 位 宽 - 在 Win 上遇到):

>>> import sys, ctypes as ct
>>>
>>>
>>> sys.platform, sys.maxsize, ct.sizeof(ct.c_void_p) * 8, ct.sizeof(ct.c_long) * 8
('win32', 9223372036854775807, 64, 32)
>>>
>>> csv.field_size_limit(sys.maxsize)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long

为避免遇到此问题,请设置(最大可能)限制 (LONG_MAX),使用技巧(感谢 @987654324 @)。它应该可以在任何 CPU / OS 上的 Python 3Python 2 上运行。

>>> csv.field_size_limit(int(ct.c_ulong(-1).value // 2))
131072
>>> limit1 = csv.field_size_limit()
>>> limit1
2147483647
>>> "0x{0:016X}".format(limit1)
'0x000000007FFFFFFF'

64 位 Python 在像 OS 这样的 Nix 上:

>>> import sys, csv, ctypes as ct
>>>
>>>
>>> sys.platform, sys.maxsize, ct.sizeof(ct.c_void_p) * 8, ct.sizeof(ct.c_long) * 8
('linux', 9223372036854775807, 64, 64)
>>>
>>> csv.field_size_limit()
131072
>>>
>>> csv.field_size_limit(int(ct.c_ulong(-1).value // 2))
131072
>>> limit1 = csv.field_size_limit()
>>> limit1
9223372036854775807
>>> "0x{0:016X}".format(limit1)
'0x7FFFFFFFFFFFFFFF'

对于 32 位 Python,无需任何技巧(如 sys.maxsizeLONG_MAX 32 位 宽)。
如果这个最大值仍然不够,那么 .csv 需要人工干预才能从 Python 进行处理。

查看以下资源了解更多详情:

【讨论】:

    【解决方案2】:

    您可以使用pandas 中的read_csv 跳过这些行。

    import pandas as pd
    
    data_df = pd.read_csv('data.csv', error_bad_lines=False)
    

    【讨论】:

    • There is no bad line ... 正如问题中所写:The csv files contains huge fields and this data needs to be analyze.
    • pandas 中的 Bad lines 概念包括超出 csv 字段限制的行。因此,如果您想跳过这些行并成功读取其他行,您可以使用此解决方案。否则,当您需要大量字段时,将字段限制增加csv.field_size_limit(100000000) 是合适的。
    • 你应该解释为什么你使用error_bad_lines
    【解决方案3】:

    csv 文件可能包含非常大的字段,因此增加field_size_limit:

    import sys
    import csv
    
    csv.field_size_limit(sys.maxsize)
    

    sys.maxsize 适用于 Python 2.x 和 3.x。 sys.maxint 仅适用于 Python 2.x (SO: what-is-sys-maxint-in-python-3)

    更新

    正如 Geoff 所指出的,上面的代码可能会导致以下错误:OverflowError: Python int too large to convert to C long。 为了避免这种情况,您可以使用以下快速而肮脏的代码(它应该适用于每个使用 Python 2 和 Python 3 的系统):

    import sys
    import csv
    maxInt = sys.maxsize
    
    while True:
        # decrease the maxInt value by factor 10 
        # as long as the OverflowError occurs.
    
        try:
            csv.field_size_limit(maxInt)
            break
        except OverflowError:
            maxInt = int(maxInt/10)
    

    【讨论】:

    • 在 Windows 7 64 位和 Python 2.6 上,maxInt = sys.maxsize 返回 9223372036854775807L,因此在调用 csv.field_size_limit(maxInt) 时会导致 TypeError: limit must be an integer。有趣的是,使用maxInt = int(sys.maxsize) 并不会改变这一点。一个粗略的解决方法是简单地使用csv.field_size_limit(2147483647),这当然会在其他平台上引起问题。在我的情况下,这很适合识别 CSV 中的损坏值,修复其他应用程序中的导出选项并消除对 csv.field_size_limit() 的需要。
    【解决方案4】:

    我刚刚在“普通”CSV 文件中遇到了这种情况。有些人可能会称其为无效的格式文件。没有转义字符,没有双引号,分隔符是分号。

    此文件中的示例行如下所示:

    第一个单元格;第二个 " 单元格,带有一个双引号和前导 空格;'部分引用'单元格;最后一个单元格

    第二个单元格中的单引号会使解析器偏离轨道。有效的是:

    csv.reader(inputfile, delimiter=';', doublequote='False', quotechar='', quoting=csv.QUOTE_NONE)
    

    【讨论】:

    • doublequotequoting=csv.QUOTE_NONE 时被忽略
    • @2Toad 很有趣。我想我需要同时指定两者,但也许我在添加quotechar=''doublequote='False'之前从未尝试过quoting=csv.QUOTE_NONE。周末会深入研究一下。
    【解决方案5】:

    找到通常放在 .cassandra 目录下的 cqlshrc 文件。

    在那个文件追加,

    [csv]
    field_size_limit = 1000000000
    

    【讨论】:

    【解决方案6】:

    下面是检查电流限制

    csv.field_size_limit()
    

    输出[20]:131072

    下面是增加限制。将其添加到代码中

    csv.field_size_limit(100000000)
    

    尝试再次检查限制

    csv.field_size_limit()
    

    输出[22]:100000000

    现在您不会收到错误“_csv.Error: field large than field limit (131072)”

    【讨论】:

    • 简单的解决方案,谢谢!
    【解决方案7】:

    有时,一行包含双引号列。当 csv 阅读器尝试阅读此行时,不理解列的结尾并触发此提升。 解决方法如下:

    reader = csv.reader(cf, quoting=csv.QUOTE_MINIMAL)
    

    【讨论】:

      【解决方案8】:

      这可能是因为您的 CSV 文件嵌入了单引号或双引号。如果您的 CSV 文件是制表符分隔的,请尝试将其打开为:

      c = csv.reader(f, delimiter='\t', quoting=csv.QUOTE_NONE)
      

      【讨论】:

      • 谢谢!!如果您正在使用 csvkit(一个优秀的 python 库和命令行 csv 工具包)并因为您的文件使用不平衡的单引号或双引号而得到原始错误,您可以通过 -u 3 命令行选项选择 QUOTE_NONE,又名 --quoting 3
      猜你喜欢
      • 2019-05-31
      • 2014-08-01
      • 2019-06-28
      • 1970-01-01
      • 1970-01-01
      • 2019-01-02
      • 2018-04-09
      相关资源
      最近更新 更多