1. ホーム
  2. python

[解決済み] S3バケット内のサブフォルダ名をboto3から取得する。

2022-07-02 02:16:45

質問

boto3を使って、AWSのS3バケットにアクセスすることができます。

s3 = boto3.resource('s3')
bucket = s3.Bucket('my-bucket-name')

さて、バケツには、フォルダ first-level というフォルダがあり、その中にタイムスタンプで名付けられたいくつかのサブフォルダがあります。 1456753904534 . 私は今やっている別の仕事のために、これらのサブフォルダーの名前を知る必要があるのですが、boto3にそれらを取得させることはできないでしょうか?

というわけで、やってみました。

objs = bucket.meta.client.list_objects(Bucket='my-bucket-name')

で、そのキー 'Contents' は、第2レベルのタイムスタンプディレクトリの代わりに、第3レベルのすべてのファイルを与える辞書を提供し、実際、私は次のようなものを含むリストを取得します。

{u'ETag': '"etag"', u'Key': first-level/1456753904534/part-00014', u'LastModified': datetime.datetime(2016, 2, 29, 13, 52, 24, tzinfo=tzutc())です。

u'Owner'(オーナー)。{u'DisplayName': 'owner', u'ID': 'id'},

u'Size': サイズ, u'StorageClass': 'storageclass'}.

を見ると、特定のファイル、この場合は part-00014 は取得されていますが、私はディレクトリの名前だけを取得したいのです。 原理的にはすべてのパスからディレクトリ名を取り除くことができますが、第2階層を取得するために第3階層のすべてを取得するのは醜く、コストも高くつきます!

私はまた、報告された何かを試してみました はこちら :

for o in bucket.objects.filter(Delimiter='/'):
    print(o.key)

と表示されますが、目的のレベルのフォルダが取得できません。

これを解決する方法はあるのでしょうか?

どのように解決するのですか?

S3はオブジェクトストレージであり、実際のディレクトリ構造を持っていない。このため、/quot;/"は化粧品のようなものです。 ディレクトリ構造を望む理由の一つは、アプリケーションにツリーを維持・剪定・追加することができるからである。S3では、このような構造は、インデックスや検索タグのようなものとして扱われます。

S3のオブジェクトを操作するには、boto3.clientかboto3.resourceが必要です。 全オブジェクトを一覧表示するには

import boto3 
s3 = boto3.client("s3")
all_objects = s3.list_objects(Bucket = 'bucket-name') 

http://boto3.readthedocs.org/en/latest/reference/services/s3.html#S3.Client.list_objects

実際には、s3オブジェクト名が'/'セパレータを使用して格納されている場合。最近の list_objects (list_objects_v2) では、指定した接頭辞で始まるキーにレスポンスを限定することができるようになりました。

特定のサブフォルダ以下のアイテムに限定する場合。

    import boto3 
    s3 = boto3.client("s3")
    response = s3.list_objects_v2(
            Bucket=BUCKET,
            Prefix ='DIR1/DIR2',
            MaxKeys=100 )

ドキュメンテーション

もう一つの選択肢は、フォルダの接頭辞を抽出するために python os.path 関数を使用することです。問題は、この場合、望ましくないディレクトリからオブジェクトをリストアップする必要があるということです。

import os
s3_key = 'first-level/1456753904534/part-00014'
filename = os.path.basename(s3_key) 
foldername = os.path.dirname(s3_key)

# if you are not using conventional delimiter like '#' 
s3_key = 'first-level#1456753904534#part-00014'
filename = s3_key.split("#")[-1]

boto3についての備忘録:boto3.resourceは素晴らしい高水準のAPIです。boto3.clientとboto3.resourceの使い分けは、一長一短です。内部共有ライブラリを開発する場合、boto3.resourceを使用すると、使用するリソースに対してブラックボックスレイヤーが得られます。