Auflisten des Inhalts eines Buckets mit boto3

198

Wie kann ich sehen, womit sich in S3 ein Bucket befindet boto3? (dh ein "ls")?

Folgendes tun:

import boto3
s3 = boto3.resource('s3')
my_bucket = s3.Bucket('some/path/')

kehrt zurück:

s3.Bucket(name='some/path/')

Wie sehe ich den Inhalt?

Amelio Vazquez-Reina
quelle

Antworten:

241

Eine Möglichkeit, den Inhalt anzuzeigen, wäre:

for my_bucket_object in my_bucket.objects.all():
    print(my_bucket_object)
garnaat
quelle
1
Kann ich die Schlüssel unter einem bestimmten Pfad im Bucket oder mit einem bestimmten Trennzeichen mit boto3 abrufen?
Rahul KP
109
Sie sollten in der Lage sein zu sagen, mybucket.objects.filter(Prefix='foo/bar')und es werden nur Objekte mit diesem Präfix aufgelistet. Sie können auch einen DelimiterParameter übergeben.
Garnaat
3
funktioniert nicht mit boto3 AttributeError: 'S3'-Objekt hat kein Attribut' Objekte '
Shek
2
@garnaat Ihr Kommentar, dass diese Filtermethode erwähnt wurde, hat mir wirklich geholfen (mein Code wurde viel einfacher und schneller) - danke!
Edward Dixon
24
Ich würde davon abraten, objecteinen Variablennamen zu verwenden, da dieser den globalen Typ beschattet object.
Oliland
100

Dies ähnelt einem 'ls', berücksichtigt jedoch nicht die Präfixordner-Konvention und listet die Objekte im Bucket auf. Es bleibt dem Leser überlassen, Präfixe herauszufiltern, die Teil des Schlüsselnamens sind.

In Python 2:

from boto.s3.connection import S3Connection

conn = S3Connection() # assumes boto.cfg setup
bucket = conn.get_bucket('bucket_name')
for obj in bucket.get_all_keys():
    print(obj.key)

In Python 3:

from boto3 import client

conn = client('s3')  # again assumes boto.cfg setup, assume AWS S3
for key in conn.list_objects(Bucket='bucket_name')['Contents']:
    print(key['Key'])
cgseller
quelle
39
Wenn Sie auch das Präfix verwenden möchten, können Sie dies folgendermaßen tun:conn.list_objects(Bucket='bucket_name', Prefix='prefix_string')['Contents']
markonovak
13
Hier werden nur die ersten 1000 Schlüssel aufgelistet. Aus der Dokumentzeichenfolge: "Gibt einige oder alle (bis zu 1000) Objekte in einem Bucket zurück." Es wird außerdem empfohlen, list_objects_v2 anstelle von list_objects zu verwenden (obwohl dies auch nur die ersten 1000 Schlüssel zurückgibt).
Brett Widmeier
3
Diese Einschränkung sollte mit Paginators
v25
44

Ich gehe davon aus, dass Sie die Authentifizierung separat konfiguriert haben.

import boto3
s3 = boto3.resource('s3')

my_bucket = s3.Bucket('bucket_name')

for file in my_bucket.objects.all():
    print(file.key)
Tushar Niras
quelle
30

Wenn Sie die Schlüssel ACCESS und SECRET übergeben möchten (was Sie nicht tun sollten, da dies nicht sicher ist):

from boto3.session import Session

ACCESS_KEY='your_access_key'
SECRET_KEY='your_secret_key'

session = Session(aws_access_key_id=ACCESS_KEY,
                  aws_secret_access_key=SECRET_KEY)
s3 = session.resource('s3')
your_bucket = s3.Bucket('your_bucket')

for s3_file in your_bucket.objects.all():
    print(s3_file.key)
Erwin Alberto
quelle
13
Dies ist weniger sicher als eine Anmeldeinformationsdatei unter ~ / .aws / credentials. Obwohl es eine gültige Lösung ist.
Nu Everest
6
Dies würde erfordern, Geheimnisse an die Quellcodeverwaltung zu übergeben. Nicht gut.
Jan Groth
2
Diese Antwort fügt nichts über die API / Mechanik der Auflistung von Objekten hinzu, während eine nicht relevante Authentifizierungsmethode hinzugefügt wird, die für alle Boto-Ressourcen gleich ist und aus Sicherheitsgründen eine schlechte Praxis darstellt
Froyke
Der Antwort zur Sicherheit wurde ein Haftungsausschluss hinzugefügt.
rjurney
Was wäre, wenn die Schlüssel von einem Schlüssel- / Geheimverwaltungssystem wie Vault (Hashicorp) bereitgestellt würden - wäre das nicht besser, als nur die Anmeldeinformationsdatei unter ~ / .aws / credentials abzulegen?
SunnyAk
25

Um große Schlüssellisten zu verarbeiten (dh wenn die Verzeichnisliste größer als 1000 Elemente ist), habe ich den folgenden Code verwendet, um Schlüsselwerte (dh Dateinamen) mit mehreren Listen zu akkumulieren (danke an Amelio oben für die ersten Zeilen). Code ist für Python3:

    from boto3  import client
    bucket_name = "my_bucket"
    prefix      = "my_key/sub_key/lots_o_files"

    s3_conn   = client('s3')  # type: BaseClient  ## again assumes boto.cfg setup, assume AWS S3
    s3_result =  s3_conn.list_objects_v2(Bucket=bucket_name, Prefix=prefix, Delimiter = "/")

    if 'Contents' not in s3_result:
        #print(s3_result)
        return []

    file_list = []
    for key in s3_result['Contents']:
        file_list.append(key['Key'])
    print(f"List count = {len(file_list)}")

    while s3_result['IsTruncated']:
        continuation_key = s3_result['NextContinuationToken']
        s3_result = s3_conn.list_objects_v2(Bucket=bucket_name, Prefix=prefix, Delimiter="/", ContinuationToken=continuation_key)
        for key in s3_result['Contents']:
            file_list.append(key['Key'])
        print(f"List count = {len(file_list)}")
    return file_list
Hephaistos
quelle
20

Meine s3- keysDienstprogrammfunktion ist im Wesentlichen eine optimierte Version von @ Hephaestus 'Antwort:

import boto3


s3_paginator = boto3.client('s3').get_paginator('list_objects_v2')


def keys(bucket_name, prefix='/', delimiter='/', start_after=''):
    prefix = prefix[1:] if prefix.startswith(delimiter) else prefix
    start_after = (start_after or prefix) if prefix.endswith(delimiter) else start_after
    for page in s3_paginator.paginate(Bucket=bucket_name, Prefix=prefix, StartAfter=start_after):
        for content in page.get('Contents', ()):
            yield content['Key']

In meinen Tests (boto3 1.9.84) ist es deutlich schneller als der entsprechende (aber einfachere) Code:

import boto3


def keys(bucket_name, prefix='/', delimiter='/'):
    prefix = prefix[1:] if prefix.startswith(delimiter) else prefix
    bucket = boto3.resource('s3').Bucket(bucket_name)
    return (_.key for _ in bucket.objects.filter(Prefix=prefix))

Da S3 binär sortierte UTF-8-Ergebnisse garantiertstart_after , wurde der ersten Funktion eine Optimierung hinzugefügt.

Sean Summers
quelle
Dies ist bei weitem die beste Antwort. Ich habe gerade die Antwort von @ Hephaestus geändert (weil sie die höchste war), als ich nach unten gescrollt habe. Dies sollte die akzeptierte Antwort sein und zusätzliche Punkte für die Prägnanz erhalten. Ich würde hinzufügen, dass der Generator aus dem zweiten Code eingewickelt werden muss list(), um eine Liste von Dateien zurückzugeben.
Richard D
@RichardD beide Ergebnisse geben Generatoren zurück. Viele Buckets, auf die ich mit diesem Code ziele, haben mehr Schlüssel, als der Speicher des Code-Executors gleichzeitig verarbeiten kann (z. B. AWS Lambda). Ich bevorzuge es, die Schlüssel zu konsumieren, wenn sie generiert werden.
Sean Summers
6

Eine sparsamere Methode, anstatt über eine for-Schleife zu iterieren, können Sie auch einfach das Originalobjekt drucken, das alle Dateien in Ihrem S3-Bucket enthält:

session = Session(aws_access_key_id=aws_access_key_id,aws_secret_access_key=aws_secret_access_key)
s3 = session.resource('s3')
bucket = s3.Bucket('bucket_name')

files_in_s3 = bucket.objects.all() 
#you can print this iterable with print(list(files_in_s3))
Daniel Vieira
quelle
3
@petezurich, können Sie bitte erklären, warum eine so geringfügige Änderung meiner Antwort - das Ersetzen eines „a“ durch ein großes „A“ zu Beginn meiner Antwort meinen Ruf um -2 herabgesetzt hat, aber ich denke, Sie und ich können zustimmen das ist nicht nur deine Korrektur überhaupt NICHT relevant, sondern eigentlich eher kleinlich, würdest du das nicht sagen? Bitte konzentrieren Sie sich eher auf den Inhalt als auf kindische Überarbeitungen, den meisten Jungen
Daniel Vieira
Dies waren zwei verschiedene Wechselwirkungen. 1. Ich habe Ihre Antwort bearbeitet, die auch für kleinere Rechtschreibfehler empfohlen wird. Ich stimme zu, dass die Grenzen zwischen geringfügig und trivial nicht eindeutig sind. Ich stimme keinem Beitrag zu, weil ich Fehler sehe und in diesem Fall nicht. Ich behebe einfach alle Fehler, die ich sehe.
Petezurich
2. Ich habe Ihre Antwort abgelehnt, weil Sie geschrieben haben, dass files_in_s3es sich um ein " Listenobjekt " handelt. In Python gibt es so etwas nicht. Es ist eher iterierbar und ich konnte Ihren Code nicht zum Laufen bringen und habe ihn daher herabgestimmt. Dann habe ich den Fehler gefunden und Ihren Standpunkt gesehen, konnte aber meine Ablehnung nicht rückgängig machen.
Petezurich
5
@petezurich kein Problem, verstanden Sie, Punkt, nur eine Sache, in Python ist eine Liste ein Objekt, weil so ziemlich alles in Python ein Objekt ist, dann folgt auch, dass eine Liste auch iterierbar ist, aber in erster Linie ist es ein Objekt! Deshalb habe ich Ihre Ablehnung nicht verstanden - Sie haben etwas abgestimmt, das korrekt war, und Code, der funktioniert. Wie auch immer, danke für Ihre Entschuldigung und alles Gute
Daniel Vieira
1
@petezurich Alles in Python ist ein Objekt. "Listenobjekt" ist völlig akzeptabel.
Zach Garwood
4

ObjectSummary:

Der ObjectSummary sind zwei Bezeichner zugeordnet:

  • Bucket_Name
  • Schlüssel

boto3 S3: ObjectSummary

Weitere Informationen zu Objektschlüsseln aus der AWS S3-Dokumentation:

Objektschlüssel:

Wenn Sie ein Objekt erstellen, geben Sie den Schlüsselnamen an, der das Objekt im Bucket eindeutig identifiziert. Wenn Sie beispielsweise in der Amazon S3-Konsole (siehe AWS Management Console) einen Bucket markieren, wird eine Liste der Objekte in Ihrem Bucket angezeigt. Diese Namen sind die Objektschlüssel. Der Name eines Schlüssels ist eine Folge von Unicode-Zeichen, deren UTF-8-Codierung höchstens 1024 Byte lang ist.

Das Amazon S3-Datenmodell ist eine flache Struktur: Sie erstellen einen Bucket und der Bucket speichert Objekte. Es gibt keine Hierarchie von Unterbuckets oder Unterordnern. Sie können jedoch mithilfe von Präfixen und Trennzeichen für Schlüsselnamen auf logische Hierarchien schließen, wie dies bei der Amazon S3-Konsole der Fall ist. Die Amazon S3-Konsole unterstützt ein Ordnerkonzept. Angenommen, Ihr Bucket (vom Administrator erstellt) enthält vier Objekte mit den folgenden Objektschlüsseln:

Entwicklung / Projekte1.xls

Finanzen / Statement1.pdf

Privat / taxdocument.pdf

s3-dg.pdf

Referenz:

AWS S3: Objektschlüssel

Hier ist ein Beispielcode, der zeigt, wie der Bucket-Name und der Objektschlüssel abgerufen werden.

Beispiel:

import boto3
from pprint import pprint

def main():

    def enumerate_s3():
        s3 = boto3.resource('s3')
        for bucket in s3.buckets.all():
             print("Name: {}".format(bucket.name))
             print("Creation Date: {}".format(bucket.creation_date))
             for object in bucket.objects.all():
                 print("Object: {}".format(object))
                 print("Object bucket_name: {}".format(object.bucket_name))
                 print("Object key: {}".format(object.key))

    enumerate_s3()


if __name__ == '__main__':
    main()
Gothburz
quelle
3

Ich habe es einfach so gemacht, einschließlich der Authentifizierungsmethode:

s3_client = boto3.client(
                's3',
                aws_access_key_id='access_key',
                aws_secret_access_key='access_key_secret',
                config=boto3.session.Config(signature_version='s3v4'),
                region_name='region'
            )

response = s3_client.list_objects(Bucket='bucket_name', Prefix=key)
if ('Contents' in response):
    # Object / key exists!
    return True
else:
    # Object / key DOES NOT exist!
    return False
Milean
quelle
2
#To print all filenames in a bucket
import boto3

s3 = boto3.client('s3')

def get_s3_keys(bucket):

    """Get a list of keys in an S3 bucket."""
    resp = s3.list_objects_v2(Bucket=bucket)
    for obj in resp['Contents']:
      files = obj['Key']
    return files


filename = get_s3_keys('your_bucket_name')

print(filename)

#To print all filenames in a certain directory in a bucket
import boto3

s3 = boto3.client('s3')

def get_s3_keys(bucket, prefix):

    """Get a list of keys in an S3 bucket."""
    resp = s3.list_objects_v2(Bucket=bucket, Prefix=prefix)
    for obj in resp['Contents']:
      files = obj['Key']
      print(files)
    return files


filename = get_s3_keys('your_bucket_name', 'folder_name/sub_folder_name/')

print(filename)
Imran Selim
quelle
Beide "get_s3_keys" geben nur den letzten Schlüssel zurück.
Alexey Vazhnov
1

Mit nur geringen Änderungen am Code von @Hephaeastus in einem der obigen Kommentare wurde die folgende Methode geschrieben, um Ordner und Objekte (Dateien) in einem bestimmten Pfad aufzulisten. Funktioniert ähnlich wie der Befehl s3 ls.

from boto3 import session

def s3_ls(profile=None, bucket_name=None, folder_path=None):
    folders=[]
    files=[]
    result=dict()
    bucket_name = bucket_name
    prefix= folder_path
    session = boto3.Session(profile_name=profile)
    s3_conn   = session.client('s3')
    s3_result =  s3_conn.list_objects_v2(Bucket=bucket_name, Delimiter = "/", Prefix=prefix)
    if 'Contents' not in s3_result and 'CommonPrefixes' not in s3_result:
        return []

    if s3_result.get('CommonPrefixes'):
        for folder in s3_result['CommonPrefixes']:
            folders.append(folder.get('Prefix'))

    if s3_result.get('Contents'):
        for key in s3_result['Contents']:
            files.append(key['Key'])

    while s3_result['IsTruncated']:
        continuation_key = s3_result['NextContinuationToken']
        s3_result = s3_conn.list_objects_v2(Bucket=bucket_name, Delimiter="/", ContinuationToken=continuation_key, Prefix=prefix)
        if s3_result.get('CommonPrefixes'):
            for folder in s3_result['CommonPrefixes']:
                folders.append(folder.get('Prefix'))
        if s3_result.get('Contents'):
            for key in s3_result['Contents']:
                files.append(key['Key'])

    if folders:
        result['folders']=sorted(folders)
    if files:
        result['files']=sorted(files)
    return result

Dadurch werden alle Objekte / Ordner in einem bestimmten Pfad aufgelistet. Ordnerpfad kann standardmäßig als Keine belassen werden, und die Methode listet den unmittelbaren Inhalt des Stammverzeichnisses des Buckets auf.

RAM
quelle
0

Hier ist die Lösung

importiere boto3

s3 = boto3.resource ('s3')

BUCKET_NAME = 'Ihr S3-Bucket-Name eg'deletemetesting11' '

allFiles = s3.Bucket (BUCKET_NAME) .objects.all ()

für Datei in allFiles: print (file.key)

Shashi Kumar Singh
quelle