【发布时间】:2016-03-15 21:08:55
【问题描述】:
我有很大的 gzip 压缩文件。
我编写了一段代码来将这些文件拆分成更小的文件。我可以指定
每个文件的行数。问题是我最近增加了每次拆分的行数
到 16,000,000,当我处理更大的文件时,不会发生拆分。有时文件更小
生产成功,有时生产了一个但重量只有40B或50B,即
失败。我试图通过查看gzip 中提出的内容来发现例外情况
代码。所以我的代码如下所示:
def writeGzipFile(file_name, content):
import gzip
with gzip.open(file_name, 'wb') as f:
if not content == '':
try:
f.write(content)
except IOError as ioe:
print "I/O ERROR wb", ioe.message
except ValueError as ve:
print "VALUE ERROR wb: ", ve.message
except EOFError as eofe:
print "EOF ERROR wb: ", eofe.message
except:
print "UNEXPECTED ERROR wb"
问题是内容太高的时候,和行数有关,我经常得到 “意外错误”消息。所以我不知道这里抛出了哪种错误。
我终于发现行数是问题所在,python 的gzip 似乎无法一次将这么多的数据写入一个文件。将每个拆分的行数降低到 4,000,000 个作品。但是,我想拆分内容并按顺序写入文件,以确保即使是高数据内容也能被写入。
所以我想知道如何找出可以使用gzip 一次性写入文件的最大字符数,而不会出现任何故障。
编辑 1
所以我发现了所有剩余的异常(我不知道可以简单地捕获 Exception 抱歉):
def writeGzipFile(file_name, content, file_permission=None):
import gzip, traceback
with gzip.open(file_name, 'wb') as f:
if not content == '':
try:
f.write(content)
except IOError as ioe:
print "I/O ERROR wb", ioe.message
except ValueError as ve:
print "VALUE ERROR wb: ", ve.message
except EOFError as eofe:
print "EOF ERROR wb: ", eofe.message
except Exception, err:
print "EXCEPTION:", err.message
print "TRACEBACK_1:", traceback.print_exc(file=sys.stdout)
except:
print "UNEXPECTED ERROR wb"
错误大约是int 大小。我从没想过有一天我会超过 int 大小:
EXCEPTION: size does not fit in an int
TRACEBACK_1:Traceback (most recent call last):
File "/home/anadin/dev/illumina-project-restructor_mass-splitting/illumina-project-restructor/tools/file_utils/file_compression.py", line 131, in writeGzipFile
f.write(content)
File "/usr/local/cluster/python2.7/lib/python2.7/gzip.py", line 230, in write
self.crc = zlib.crc32(data, self.crc) & 0xffffffffL
OverflowError: size does not fit in an int
None
好的,所以 int 的最大大小为 2,147,483,647,根据我的日志,我的数据块约为 3,854,674,090。这个块是一个字符串,我对其应用了__len__() 函数。
因此,正如我计划的那样,正如 Antti Haapala 所建议的那样,我将一次读取较小的块,以便按顺序将它们写入较小的文件。
【问题讨论】:
-
Ans 当你解决了这个问题 - 不要使用未命名的异常块 - 因为它们通过隐藏故障机制而导致这类问题。 (除非您真的不在乎操作是否失败)。
-
如果它在您减少正在处理的数据量时有效,那么我很确定问题在于您将 所有 数据保存在单个字符串:
content。这可能会耗尽你所有的内存。我看不到您的其余代码,但通常您想读取一小块数据(通常是一行),随心所欲地处理它,然后将其提供给 gzip,然后将那一小块写入磁盘.然后,您重复这 1600 万次(或经常),并且占用的内存绝不会超过一行... -
FWIW, this answer 我几年前写的展示了如何逐块压缩文件。
标签: python python-2.7 gzip