Überprüfen Sie mit boto3, ob ein Schlüssel in einem Bucket in s3 vorhanden ist

Lesezeit: 6 Minuten

Ich würde gerne wissen, ob ein Schlüssel in boto3 existiert. Ich kann den Inhalt des Buckets wiederholen und den Schlüssel überprüfen, ob er übereinstimmt.

Aber das scheint länger und übertrieben. In den offiziellen Boto3-Dokumenten wird ausdrücklich angegeben, wie dies zu tun ist.

Vielleicht übersehe ich das Offensichtliche. Kann mir jemand sagen, wie ich das erreichen kann.

Uberprufen Sie mit boto3 ob ein Schlussel in einem Bucket
Wandern Nauta

Boto 2 boto.s3.key.Key Objekt hatte früher eine exists Methode, die überprüft hat, ob der Schlüssel auf S3 existiert, indem sie eine HEAD-Anfrage durchführt und das Ergebnis betrachtet, aber anscheinend nicht mehr existiert. Du musst es selber machen:

import boto3
import botocore

s3 = boto3.resource('s3')

try:
    s3.Object('my-bucket', 'dootdoot.jpg').load()
except botocore.exceptions.ClientError as e:
    if e.response['Error']['Code'] == "404":
        # The object does not exist.
        ...
    else:
        # Something else has gone wrong.
        raise
else:
    # The object does exist.
    ...

load() führt eine HEAD-Anforderung für einen einzelnen Schlüssel aus, was schnell ist, selbst wenn das fragliche Objekt groß ist oder Sie viele Objekte in Ihrem Bucket haben.

Natürlich können Sie überprüfen, ob das Objekt vorhanden ist, weil Sie es verwenden möchten. Wenn das der Fall ist, können Sie das einfach vergessen load() und mach ein get() oder download_file() direkt, dann behandeln Sie den Fehlerfall dort.

  • Danke für die schnelle Antwort Wanderer. Ich brauche nur das gleiche für boto3.

    – Prabhakar Shanmugam

    21. November ’15 um 12:19

  • Für boto3, es scheint das Beste, was Sie im Moment tun können, ist anzurufen head_object um zu versuchen, die Metadaten für den Schlüssel abzurufen, und dann den resultierenden Fehler zu behandeln, falls er nicht existiert.

    – Wandern Nauta

    21. November ’15 um 12:35


  • Oh, das oben head_bucket Vorschlag funktioniert nur für Eimer, nicht für Objekte. Ich ziehe meinen Vorschlag zurück. 🙂

    – Eisenkissen

    9. Okt. 17 um 7:14 Uhr

  • -1; funktioniert bei mir nicht. Auf boto3-Version 1.5.26 sehe ich e.response['Error']['Code'] einen Wert haben wie "NoSuchKey", nicht "404". Ich habe nicht überprüft, ob dies auf einen Unterschied in den Bibliotheksversionen oder eine Änderung in der API selbst zurückzuführen ist, seit diese Antwort geschrieben wurde. So oder so, in meiner Version von boto3, ein kürzerer Ansatz als das Überprüfen e.response['Error']['Code'] ist nur zu fangen s3.meta.client.exceptions.NoSuchKey an erster Stelle.

    – Mark Amery

    20. Februar ’18 um 17:02

  • wenn du ein s3 verwendest client (im Gegensatz zu a resource) dann mach s3.head_object(Bucket='my_bucket', Key='my_key') anstatt s3.Object(...).load()

    – Benutzer2426679

    27. Apr. ’20 um 23:20


Uberprufen Sie mit boto3 ob ein Schlussel in einem Bucket
o_c

Der einfachste Weg, den ich gefunden habe (und wahrscheinlich der effizienteste), ist dieser:

import boto3
from botocore.errorfactory import ClientError

s3 = boto3.client('s3')
try:
    s3.head_object(Bucket="bucket_name", Key='file_path')
except ClientError:
    # Not found
    pass

  • Hinweis: Sie müssen aws_access_key_id/aws_secret_access_key usw. nicht übergeben, wenn Sie eine Rolle verwenden oder die Schlüssel in Ihrer .aws-Konfiguration haben, können Sie einfach tun s3 = boto3.client('s3')

    – Andy Hayden

    21. Juni ’17 um 0:46

  • Ich denke, das Hinzufügen dieses Tests gibt Ihnen etwas mehr Sicherheit, dass das Objekt wirklich nicht existiert, anstatt dass ein anderer Fehler die Ausnahme auslöst – beachten Sie, dass ‘e’ die ClientError-Ausnahmeinstanz ist: if e.response['ResponseMetadata']['HTTPStatusCode'] == 404:

    – Richard

    10. Juli ’17 um 16:17


  • @Taylor es ist eine Get-Anfrage, aber ohne Datenübertragung.

    – Andy Hayden

    20. Dez. 17 um 19:36 Uhr

  • ClientError ist ein Catch-All für 400, nicht nur für 404, daher ist es nicht robust.

    – mickzer

    7. Januar ’20 um 16:43

  • @mickzer du hast recht. Es ist besser, einen S3.Client.Exceptions.NoSuchKey auszuschließen.

    – Neau Adrien

    10. Juli ’20 um 12:53

1641662585 395 Uberprufen Sie mit boto3 ob ein Schlussel in einem Bucket
Böser Puppenmeister

Ich bin kein großer Fan davon, Ausnahmen für den Kontrollfluss zu verwenden. Dies ist ein alternativer Ansatz, der in boto3 funktioniert:

import boto3

s3 = boto3.resource('s3')
bucket = s3.Bucket('my-bucket')
key = 'dootdoot.jpg'
objs = list(bucket.objects.filter(Prefix=key))
if any([w.key == path_s3 for w in objs]):
    print("Exists!")
else:
    print("Doesn't exist")

  • Danke für das Update EvilPuppetMaster. Als ich das letzte Mal nachgesehen habe, hatte ich leider keine Zugriffsrechte für Listen-Buckets. Ihre Antwort passt zu meiner Frage, daher habe ich Sie gewählt. Aber die erste Antwort hatte ich schon lange vorher als Antwort markiert. Danke für Ihre Hilfe.

    – Prabhakar Shanmugam

    5. Januar ’16 um 7:19


  • Zählt dies nicht als Angebotsanfrage (12,5x teurer als erhalten)? Bei 100 Millionen Objekten könnte das etwas teuer werden… Ich habe das Gefühl, dass die Fang-Ausnahme-Methode bisher leider die beste ist.

    – Pierre D

    5. Mai ’16 um 1:04

  • Liste kann pro Anfrage 12,5x so teuer sein, aber eine einzelne Anfrage kann auch 100 Millionen Objekte zurückgeben, von denen ein einzelnes Get nur eines zurückgeben kann. In Ihrem hypothetischen Fall wäre es also billiger, alle 100 Millionen mit Liste zu holen und dann lokal zu vergleichen, als 100 Millionen einzelne zu bekommen. Ganz zu schweigen von 1000x schneller, da Sie nicht für jedes Objekt den HTTP-Roundtrip benötigen würden.

    – EvilPuppetMaster

    7. Mai ’16 um 9:31


  • @ user3186866 Das liegt daran, dass S3 keine “Ordner” hat. Alle Objekte existieren als Dateien in ihren angegebenen Pfaden. Ordner sind ein Werkzeug, das uns hilft, die Struktur unseres Speichers zu organisieren und zu verstehen, aber in Wirklichkeit sind S3-Buckets genau das, Buckets.

    – ibtokin

    16. Dezember ’19 um 17:39


  • Nach dem erneuten Ausführen mit Debug sieht es aus wie bucket.objects.filter(Prefix=key).limit(1) schränkt nicht die tatsächliche Antwort von S3 ein, sondern nur die zurückgegebene Sammlung auf der Clientseite. Stattdessen solltest du bucket.objects.filter(Prefix=key, MaxKeys=1) wie @FangZhang oben vorgeschlagen hat

    – Benav

    30. Juli ’20 um 1:03


Sie können verwenden S3Fs, das im Wesentlichen ein Wrapper um boto3 ist, der typische Operationen im Dateisystemstil offenlegt:

import s3fs
s3 = s3fs.S3FileSystem()
s3.exists('myfile.txt')

  • Hatte dabei ein Problem. list_objects(“2000”) gibt Schlüssel wie “2000-01”, “2000-02” zurück

    – G. Cheng

    27. März ’17 um 3:15

  • Dies gibt nur bis zu 1000 Objekte zurück! boto3.amazonaws.com/v1/documentation/api/latest/reference/…

    – RoachLord

    17. Dez. ’18 um 19:42

  • Dies ist die effizienteste Lösung, da dies nicht erforderlich ist s3:GetObject Berechtigungen nur die s3:ListBucket Berechtigungen

    – Vishrant

    27. Juni ’20 um 23:35

1641662585 618 Uberprufen Sie mit boto3 ob ein Schlussel in einem Bucket
Wunder

Angenommen, Sie möchten nur überprüfen, ob ein Schlüssel vorhanden ist (anstatt ihn leise zu überschreiben), führen Sie zuerst diese Überprüfung durch:

import boto3

def key_exists(mykey, mybucket):
  s3_client = boto3.client('s3')
  response = s3_client.list_objects_v2(Bucket=mybucket, Prefix=mykey)
  if response:
      for obj in response['Contents']:
          if mykey == obj['Key']:
              return True
  return False

if key_exists('someprefix/myfile-abc123', 'my-bucket-name'):
    print("key exists")
else:
    print("safe to put new bucket object")
    # try:
    #     resp = s3_client.put_object(Body="Your string or file-like object",
    #                                 Bucket=mybucket,Key=mykey)
    # ...check resp success and ClientError exception for errors...

Nicht nur client aber bucket auch:

import boto3
import botocore
bucket = boto3.resource('s3', region_name="eu-west-1").Bucket('my-bucket')

try:
  bucket.Object('my-file').get()
except botocore.exceptions.ClientError as ex:
  if ex.response['Error']['Code'] == 'NoSuchKey':
    print('NoSuchKey')

Uberprufen Sie mit boto3 ob ein Schlussel in einem Bucket
Fang Zhang

Dies könnte sowohl das Präfix als auch den Schlüssel überprüfen und ruft höchstens 1 Schlüssel ab.

def prefix_exits(bucket, prefix):
    s3_client = boto3.client('s3')
    res = s3_client.list_objects_v2(Bucket=bucket, Prefix=prefix, MaxKeys=1)
    return 'Contents' in res

.

185030cookie-checkÜberprüfen Sie mit boto3, ob ein Schlüssel in einem Bucket in s3 vorhanden ist

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy