_csv.Error:字段大于字段限制(131072)
- 2025-02-14 09:50:00
- admin 原创
- 58
问题描述:
我有一个脚本,正在读取一个包含非常大字段的 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 文件?跳过包含大量字段的行是不可能的,因为数据需要在后续步骤中进行分析。
解决方案 1:
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)
解决方案 2:
这可能是因为您的 CSV 文件嵌入了单引号或双引号。如果您的 CSV 文件是制表符分隔的,请尝试以以下方式打开它:
c = csv.reader(f, delimiter=' ', quoting=csv.QUOTE_NONE)
解决方案 3:
.csv字段大小通过 [Python.Docs] 控制:csv.field_size_limit([new_limit])(重点是我的):
返回解析器当前允许的最大字段大小。如果给出了new_limit,则这将成为新的限制。
它默认设置为131072或0x20000(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 数据类型),其大小根据CPU架构和操作系统(ILP)而变化。经典区别:对于64 位 操作系统(和Python构建),long类型大小(以位为单位*)*为:
尼克斯:64
获胜:32
当尝试设置它时,将检查新值是否在长边界内,这就是为什么在某些情况下会弹出另一个异常(因为sys.maxsize通常为064位宽 - 在Win上遇到):
>>> import sys, ctypes as ct >>> >>> >>> "v{:d}.{:d}.{:d}".format(*sys.version_info[:3]), sys.platform, sys.maxsize, ct.sizeof(ct.c_void_p) * 8, ct.sizeof(ct.c_long) * 8 ('v3.9.9', '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)(感谢[Python.Docs]: ctypes - Python 的外部函数库)。它应该可以在任何CPU / OS上的Python 3和Python 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'
类似Nix操作系统上的064 位Python:
>>> import sys, csv, ctypes as ct >>> >>> >>> "v{:d}.{:d}.{:d}".format(*sys.version_info[:3]), sys.platform, sys.maxsize, ct.sizeof(ct.c_void_p) * 8, ct.sizeof(ct.c_long) * 8 ('v3.8.10', '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.maxsize和LONG_MAX都是32位宽)。
如果这个最大值仍然不够,那么.csv就需要手动干预才能从Python进行处理。
请查看以下资源以了解更多详细信息:
使用Python中的C类型边界:[SO]:Python 中的 C 类型整数的最大值和最小值(@CristiFati 的答案)
Python 064 位 与 032 位之间的区别:[SO]:如何确定我的 Python shell 在 OS X 上是在 32 位模式还是 64 位模式下执行?(@CristiFati 的回答)
解决方案 4:
下面是检查当前限制
csv.field_size_limit()
出局[20]: 131072
以下是增加限制的方法。将其添加到代码中
csv.field_size_limit(100000000)
尝试再次检查限制
csv.field_size_limit()
出[22]: 100000000
现在您不会收到错误“_csv.Error:字段大于字段限制(131072)”
解决方案 5:
我刚刚在一个“普通” CSV 文件上遇到了这种情况。有些人可能会称其为无效格式的文件。没有转义字符,没有双引号,分隔符是分号。
该文件的示例行如下所示:
第一个单元格;第二个“带有一个双引号和前导空格的单元格;'部分引用' 单元格;最后一个单元格
第二个单元格中的单引号会使解析器失控。有效的方法是:
csv.reader(inputfile, delimiter=';', doublequote='False', quotechar='', quoting=csv.QUOTE_NONE)
解决方案 6:
有时,一行包含双引号列。当 csv 读取器尝试读取此行时,无法理解列的结尾并触发此引发。解决方案如下:
reader = csv.reader(cf, quoting=csv.QUOTE_MINIMAL)
解决方案 7:
您可以使用error_bad_lines
选项pd.read_csv
跳过这些行。
import pandas as pd
data_df = pd.read_csv('data.csv', error_bad_lines=False)
这是有效的,因为 pandas 中定义的“坏行”包括其中一个字段超出 csv 限制的行。
请注意,此解决方案仅当您的 csv 文件中的字段不应这么长时才有效。如果您预计字段大小很大,这会丢弃您的数据。
解决方案 8:
找到通常放在.cassandra目录中的cqlshrc文件。
在该文件附加中,
[csv]
field_size_limit = 1000000000