使用 dask 转换大量文件的最佳方法是什么?

时间:2021-03-09 15:57:53

标签: dask

我在 s3 中有大量相对较小的文件。我需要读取每个文件,进行一些处理,然后将它们写回 Google Cloud Storage。每个文件都足够小以适合内存。保留每个文件的名称和内容很重要。

用于跨多个内核/线程扩展这项工作的最佳 dask 抽象是什么?

我尝试使用 dask.bag 处理文件并成功处理小批量文件,但在尝试处理大量文件时遇到内存问题。

我在读取文件时使用了 include_path 但无法找到一种方法让 to_textfiles 在没有首先创建路径列表的情况下使用路径信息,这需要在第一个之前读取内存中的所有文件转换后的文件被写入。

这是我尝试的:

import json
import dask.bag as db

from dask.distributed import performance_report
from dask.distributed import Client

def transform_data(data):
    extracted_at = data.pop("extracted_at")
    return dict(extracted_at=extracted_at, data=data)


def transform_file(file):
    """ We need to separate json lines, manipulate each record, and return a json string
    """
    contents, path = file
    data = [
        json.dumps(transform_data(json.loads(line)))
        for line in contents.replace("}{", "}\n{").splitlines() # fix missing \n between json strings
    ]
    return "\n".join(data), path


def get_paths(path):
    return path[-1].replace(".gz", ".jsonl.gz")


if __name__ == "__main__":
    client = Client(processes=False, n_workers=4)
    b = db.read_text("s3://mybucket/prefix/**/*.gz", include_path=True)

    with performance_report():
        xformed = b.map(transform_file)
        data = xformed.map(lambda x: x[0])  # each item is a tuple of (data, path)
        paths = xformed.map(get_paths).compute()
        data.to_textfiles(paths)

是否可以在处理文件时写入文件以避免内存问题? bag 不是这个用例的最佳抽象吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

<块引用>

是否可以在处理文件时写入文件以避免内存问题?

是的,这是可能的。

<块引用>

bag 难道不是这个用例的最佳抽象吗?

我不认为这是最好的情况,因为您正在逐个文件地处理数据,而 bag/dataframe 的想法是将数据视为单个对象。因此,如果您要查询这些文件以获得某些特定结果(如文档中的示例),bag 会很棒。此处最合适的 dask 工具是 delayed API。

相关问题