【发布时间】:2020-04-24 10:13:10
【问题描述】:
我有一个文件夹,里面装满了用 gzip 压缩的 json 文件(~10gb,主要是文本数据)。我目前的代码可以运行,但速度非常慢(想想几个小时):
from glob import glob
filenames = glob('folder_path/*')
dataframes = [pd.read_json(f, compression='gzip') for f in filenames]
我希望找到一种更快的方法来解压缩所有文件,并将每个文件保存到 pandas df 或全部保存到单个 df(此时 1 与多个 df 对我来说并不重要)。我读过zlib 但这似乎不适用于gzip 文件?我也在那里尝试了一些不同的方法,但似乎都没有,例如:
filenames = glob('folder_path/*')
jsonobjs = [gzip.open(f, 'rb') for f in filenames]
返回:
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-12-a5a84131bb38> in <module>
1 filenames = glob('folder_path/*')
----> 2 jsonobjs = [gzip.open(f, 'rb') for f in filenames]
<ipython-input-12-a5a84131bb38> in <listcomp>(.0)
1 filenames = glob('folder_path/*')
----> 2 jsonobjs = [gzip.open(f, 'rb') for f in filenames]
~/anaconda3/lib/python3.7/gzip.py in open(filename, mode, compresslevel, encoding, errors, newline)
51 gz_mode = mode.replace("t", "")
52 if isinstance(filename, (str, bytes, os.PathLike)):
---> 53 binary_file = GzipFile(filename, gz_mode, compresslevel)
54 elif hasattr(filename, "read") or hasattr(filename, "write"):
55 binary_file = GzipFile(None, gz_mode, compresslevel, filename)
~/anaconda3/lib/python3.7/gzip.py in __init__(self, filename, mode, compresslevel, fileobj, mtime)
161 mode += 'b'
162 if fileobj is None:
--> 163 fileobj = self.myfileobj = builtins.open(filename, mode or 'rb')
164 if filename is None:
165 filename = getattr(fileobj, 'name', '')
OSError: [Errno 24] Too many open files: 'folder_path/d2ea1c35275b495fb73cb123cdf4fe4c'
和
with gzip.open(glob('folder_path/*'), 'rb') as f:
file_content = f.read()
返回:
TypeError Traceback (most recent call last)
<ipython-input-10-bd68570238cd> in <module>
----> 1 with gzip.open(glob('folder_path/*'), 'rb') as f:
2 file_content = f.read()
TypeError: 'module' object is not callable
所以这个:
with gzip.open('single_file', 'rb') as f:
file_content = f.read()
pd.read_json(file_content)
工作得很好,比将 compression='gzip' 传递给 pd.read_json 更快,但我不知道如何让它适用于所有文件。
编辑: 尝试了以下方法:
for file_name in glob('folder_path/*'):
with [gzip.open(f, 'rb') for f in filenames]:
file_name = pd.read_json(f)
但返回相同的too many open files 错误
【问题讨论】:
-
也许试试 dask? docs.dask.org/en/latest/…
-
我刚刚使用
pd.read_json对一些随机生成的 gzip 压缩 JSON 文件进行了快速测试。 1000 个文件,每个文件 40 kb 的压缩数据,因此总数据量为 40 MB。解压后的大小为 120kb。当使用pd.read_json读入每个文件时,python 内存占用增加了 5-6 MB。因此,如果您一次浏览 10 GB 的文件,这将使用大量内存。你有多少内存?我很惊讶这会为你完成。数据的最终目标是什么?这一切都需要一次处理吗? -
@totalhack 这一切都需要立即处理。目前打开所有文件大约需要一整天,实际上我有 4 个这些文件的文件夹(总共约 40GB),最终都需要打开、转换和组合。我正在为此寻找多核或分布式解决方案,但我没有太多实际实施的经验。
-
如果我的示例中的内存使用量对您来说甚至遥遥无期,那么您将需要几 TB 的内存来一次保存所有这些。并且您可能需要多个数据,具体取决于您将数据存储在内存中后要对数据执行的操作。如果您可以提供有关您尝试对数据做什么的更多详细信息,那将很有帮助。你必须使用熊猫吗?当您尝试使用 gzip.open 时出了什么问题?您可以拥有多个 DF 的事实向我表明,您实际上可能并不需要一次全部存储在内存中。
-
@totalhack 编辑了帖子以包含更多回溯。如果我找到了一种快速打开和转换文件的方法,但这会导致多个 dfs,我将不得不将它们合并为下一步。
标签: python json pandas gzip unzip