【问题标题】:How to read multiple JSON files from GCS bucket in google dataflow apache beam python如何从谷歌数据流apache束python中的GCS存储桶中读取多个JSON文件
【发布时间】:2023-03-06 17:17:01
【问题描述】:

我在 GCS 中有一个包含 JSON 文件列表的存储桶。我来提取文件名列表使用

def list_blobs(bucket_name):


    storage_client = storage.Client()

    blobs = storage_client.list_blobs(bucket_name)
    json_paths = []
    for blob in blobs:
        json_paths.append(f"gs://{bucket_name}/{blob.name}")
    return json_paths

现在我想将此文件名列表传递给 apache Beam 以读取它们。我写了这段代码,但它似乎不是一个好的模式

for i,file in enumerate(list_files):
        print("parsing file:", file)
        concat_data = (p |'Data {}'.format(i) >> ReadFromText(file)
        )
        final_result.append(concat_data)

你以前遇到过同样的问题吗?

【问题讨论】:

  • 您检查过 ReadAll 转换吗?
  • @Iñigo 你能看一下我对 Batra 先生回答的回复吗

标签: python google-cloud-dataflow apache-beam


【解决方案1】:

最后我开始使用谷歌云存储作为阅读API。

列出桶的所有元素

def list_blobs(bucket_name):
"""Lists all the blobs in the bucket."""

storage_client = storage.Client()
blobs = storage_client.list_blobs(bucket_name)
json_paths = []
for blob in blobs:
    #json_paths.append(f"gs://{bucket_name}/{blob.name}")
    json_paths.append(f"{blob.name}")
return json_paths

我创建了这个 ParDo 来阅读内容

class ReadFileContent(beam.DoFn):

def setup(self):
    # Called whenever the DoFn instance is deserialized on the worker.
    # This means it can be called more than once per worker because multiple instances of a given DoFn subclass may be created (e.g., due to parallelization, or due to garbage collection after a period of disuse).
    # This is a good place to connect to database instances, open network connections or other resources.
    self.storage_client = storage.Client()

def process(self, file_name, bucket_name):
    bucket = self.storage_client.get_bucket(bucket_name)
    blob = bucket.get_blob(file_name)
    yield blob.download_as_string()

而 mu 管道看起来像这样:

list_files = list_blobs(bucket_name)

with beam.Pipeline(options=pipeline_options) as p:

    results = (
        p | 'Create' >> beam.Create(list_files)
          | 'Read each file content' >> beam.ParDo(ReadFileContent(), bucket_name)
          | 'next transformation' >> ...

【讨论】:

    【解决方案2】:

    查看this 链接。 ReadFromText 是一个有助于读取文本文件的 PTransform。另一方面,ReadAllFromText 是一个读取 PCollection 文本文件的 PTransform。读取文本文件或文件模式的 PCollection 并生成字符串的 PCollection。

    【讨论】:

    • 我在 ReadAllFromText 中发现的问题是将我的整个 JSON 文件读入一个字符串文本,当它传递到下一个转换时,它会分别读取每一行 .. 我需要的是将每一行的整个 json 字符串单独处理。
    • 在这种情况下,我建议不要使用 ReadFromText。而是使用来自 python 的 Json 模块。代码看起来像这样 beam.Create([list of file]) beam.Map(transform_json) ...... 在 transform_json 函数中,您可以使用该模块中的 fn。例如 def transform_json(file_path): with open(file_path) as f: json.load(f) 这里是链接docs.python.org/3/library/json.html#json.load
    • 这就是我的想法,我创建了一个函数,用于使用 google-storage API 读取存储在 GCS 存储桶中的 JSON 文件的内容,然后使用 JSON 模块读取内容并将其传递给下一个转变。我担心每次创建存储 API 实例并调用 GCS 获取文件内容时处理数十万 JSON 文件的模式是否不好
    • 我发现 DoFn.setup() 方法,根据文档,它是连接数据库实例、打开网络连接或其他资源的好地方。 beam.apache.org/releases/pydoc/2.32.0/…
    猜你喜欢
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多