【问题标题】:How do I list all the top-level folders in given GCS bucket?如何列出给定 GCS 存储桶中的所有顶级文件夹?
【发布时间】:2021-10-19 17:19:58
【问题描述】:

我开始

    client = storage.Client()
    bucket = client.get_bucket(BUCKET_NAME)

    <what's next? Need something like client.list_folders(path)>

我知道如何:

  1. 列出所有带有bucket.list_blobs()的blob(包括子文件夹中任意深度的blob)

  2. 或者如何使用bucket.list_blobs(prefix=&lt;path to subfolder&gt;)递归地列出给定文件夹中的所有blob

但是如果我的文件系统结构有100 顶级文件夹,每个文件夹都有数千个文件。有什么有效的方法可以只获取那些 100 顶级文件夹名称而不列出所有内部 blob?

【问题讨论】:

  • 是的,只处理返回的prefixes。我没有要发布的示例。 Google Cloud Storage 使用prefixseparator 来方便列出对象。希望这个提示对您有所帮助。
  • @JohnHanley 关于“prefixes”的优秀提示。但是,在您迭代 list_blobs 第一个元素之前,它不会加载。 PS 实际上是 delimiter 而不是 GCS 上的 separator 但我们知道你的意思。

标签: python google-cloud-platform google-cloud-storage


【解决方案1】:

这里的所有响应都有一个答案,但您需要在加载的 list_blobs(...) 迭代器中组合:prefixdelimiterprefixes。让我扔下代码来获取 100 个顶级文件夹,然后我们将逐步完成它。

import google.cloud.storage as gcs
client = gcs.Client()
blobs = client.list_blobs(
    bucket_or_name=BUCKET_NAME, 
    prefix="", 
    delimiter="/", 
    max_results=1
)
next(blobs, ...) # Force list_blobs to make the api call (lazy loading)
print(blobs.prefixes[:100])

在前八行中,我们构建 GCS 客户端并调用 client.list_blobs(...)。在您的问题中,您提到了 bucket.list_blobs(..) 方法 - 从 1.43 版开始,这仍然有效,但 the page on Buckets in the docs 说现在已弃用。唯一的区别是第 4 行的关键字 arg bucket_or_name

我们希望文件夹位于顶层,因此我们实际上根本不需要指定 prefix,但是,如果您想在顶层列出文件夹,其他读者知道这将很有用目录stuff 那么你应该指定一个斜杠。然后这个 kwarg 会变成prefix="stuff/"

有人已经提到了delimiter kwarg,但是要进行迭代,您应该指定它,以便 GCS 知道如何将 blob 名称解释为目录。很简单。

max_results=1 是为了提高效率。请记住,我们在这里不需要 blob,我们只需要文件夹名称。因此,如果我们告诉 GCS 一旦找到单个 blob 就停止查找,它可能会更快。在实践中,我没有发现这种情况,但如果你有大量的 blob,或者存储是冷线或其他什么,它很容易出现。 YMMV。认为它是可选的。

返回的blobs 对象是一个延迟加载迭代器,这意味着它不会加载——包括甚至不填充其成员——直到进行第​​一次 api 调用。为了获得第一次调用,我们要求迭代器中的 next 元素。在您的情况下,您知道您至少有一个文件,因此只需调用 next(blobs) 即可。它获取下一行(在行前)的 blob,然后将其丢弃。

但是,如果您不能保证至少有一个 blob,那么需要从交互器返回某些内容的 next(blobs) 将引发 StopIteration 异常。为了解决这个问题,我们将省略号的默认值设为...

现在我们想要的blobs 的成员prefixes 已加载,我们打印出前100 个。输出将类似于:

{'dir0/','dir1/','dir2/', ...}

【讨论】:

    【解决方案2】:

    如果不列出所有内部 blob,我认为您无法获得 100 个顶级文件夹。 Google Cloud Storage 没有文件夹或子目录,该库只是创建了分层文件树的错觉。

    我使用了这个简单的代码:

    from google.cloud import storage
    storage_client = storage.Client()
    blobs = storage_client.list_blobs('my-project')
    res = []
    
    for blob in blobs:
       if blob.name.split('/')[0] not in res:
           res.append(blob.name.split('/')[0]) 
    
    print(res) 
    

    【讨论】:

    • “Google Cloud Storage 没有文件夹或子目录”-> 这也是我的想法。谢谢!
    • 这不是真的 - 你错过了delimiter 参数。
    • 如果我的说法不正确,请为这种情况添加一个可行的解决方案
    • 不正确。它可以在不列出所有内部 blob 的情况下完成。
    【解决方案3】:

    您可以使用分隔列表获取顶级前缀。请参阅list_blobs 文档:

    delimiter (str) - (可选)分隔符,与前缀一起使用以模拟 层次结构。

    类似这样的:

    from google.cloud import storage
    storage_client = storage.Client()
    storage_client.list_blobs(BUCKET_NAME, delimiter='/')
    

    【讨论】:

    • 对我来说,您的代码不起作用,这就是起作用的方法: storage_client.list_blobs('my-bucket', prefix='source/',delimiter='/'),
    • @marian.vladoi - 你是说delimiter 没有prefix 就不能工作吗?情况不应该如此。
    • 对我不起作用,不知何故仍然列出了子目录中的所有 blob。您发布的文档也很模糊。
    猜你喜欢
    • 1970-01-01
    • 2020-09-17
    • 2021-06-13
    • 2021-09-29
    • 2017-12-23
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 2014-07-18
    相关资源
    最近更新 更多