it-swarm.com.de

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

Ich würde gerne wissen, ob in boto3 ein Schlüssel vorhanden ist. Ich kann den Inhalt des Eimers wiederholen und den Schlüssel überprüfen, ob er passt.

Aber das scheint länger und übertrieben zu sein. Offizielle Dokumente von Boto3 legen explizit fest, wie dies geschehen soll. 

Vielleicht vermisse ich das Offensichtliche. Kann mir jemand zeigen, wie ich das erreichen kann.

86

Das boto.s3.key.Key-Objekt von Boto 2 verwendete früher eine exists-Methode, die überprüft hat, ob der Schlüssel in S3 vorhanden war, indem eine HEAD -Anforderung ausgeführt und das Ergebnis betrachtet wurde. Es scheint jedoch, dass es keinen mehr gibt. 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() fordert eine HEAD - Anforderung für einen einzelnen Schlüssel an. Dies ist schnell, auch wenn das betreffende Objekt groß ist oder sich viele Objekte in Ihrem Bucket befinden.

Natürlich prüfen Sie möglicherweise, ob das Objekt vorhanden ist, da Sie es verwenden möchten. Wenn dies der Fall ist, können Sie die load() einfach vergessen und eine get() oder download_file() direkt ausführen, um dort den Fehlerfall zu behandeln.

117
Wander Nauta

Ich bin kein großer Fan von Ausnahmen für den Kontrollfluss. 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 len(objs) > 0 and objs[0].key == key:
    print("Exists!")
else:
    print("Doesn't exist")
76

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

import boto3
from botocore.errorfactory import ClientError

s3 = boto3.client('s3', aws_access_key_id='aws_key', aws_secret_access_key='aws_secret')
try:
    s3.head_object(Bucket='bucket_name', Key='file_path')
except ClientError:
    # Not found
    pass
60
o_c

Wenn Sie in Boto3 nach einem Ordner (Präfix) oder einer Datei suchen, die list_objects verwendet. Sie können das Vorhandensein von 'Inhalt' im Antwortdict als eine Überprüfung verwenden, ob das Objekt vorhanden ist. Dies ist eine andere Methode, um die try/mit Ausnahme von @EvilPuppetMaster zu vermeiden

import boto3
client = boto3.client('s3')
results = client.list_objects(Bucket='my-bucket', Prefix='dootdoot.jpg')
return 'Contents' in results
14
Lucian Thorr

Nicht nur client, sondern auch bucket:

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')
10

Versuchen Sie dies einfach

import boto3
s3 = boto3.resource('s3')
bucket = s3.Bucket('mybucket_name') # just Bucket name
file_name = 'A/B/filename.txt'      # full file path
obj = list(bucket.objects.filter(Prefix=file_name))
if len(obj) > 0:
    print("Exists")
else:
    print("Not Exists")
2
Alkesh Mahajan

FWIW, hier sind die sehr einfachen Funktionen, die ich verwende

import boto3

def get_resource(config: dict={}):
    """Loads the s3 resource.

    Expects AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to be in the environment
    or in a config dictionary.
    Looks in the environment first."""

    s3 = boto3.resource('s3',
                        aws_access_key_id=os.environ.get(
                            "AWS_ACCESS_KEY_ID", config.get("AWS_ACCESS_KEY_ID")),
                        aws_secret_access_key=os.environ.get("AWS_SECRET_ACCESS_KEY", config.get("AWS_SECRET_ACCESS_KEY")))
    return s3


def get_bucket(s3, s3_uri: str):
    """Get the bucket from the resource.
    A thin wrapper, use with caution.

    Example usage:

    >> bucket = get_bucket(get_resource(), s3_uri_prod)"""
    return s3.Bucket(s3_uri)


def isfile_s3(bucket, key: str) -> bool:
    """Returns T/F whether the file exists."""
    objs = list(bucket.objects.filter(Prefix=key))
    return len(objs) == 1 and objs[0].key == key


def isdir_s3(bucket, key: str) -> bool:
    """Returns T/F whether the directory exists."""
    objs = list(bucket.objects.filter(Prefix=key))
    return len(objs) > 1
1
Andy Reagan
import boto3
client = boto3.client('s3')
s3_key = 'Your file without bucket name e.g. abc/bcd.txt'
bucket = 'your bucket name'
content = client.head_object(Bucket=bucket,Key=s3_key)
    if content.get('ResponseMetadata',None) is not None:
        print "File exists - s3://%s/%s " %(bucket,s3_key) 
    else:
        print "File does not exist - s3://%s/%s " %(bucket,s3_key)
1
Vivek

Bei boto3 kann mit ObjectSummary geprüft werden, ob ein Objekt vorhanden ist.

Enthält die Zusammenfassung eines Objekts, das in einem Amazon S3-Bucket gespeichert ist. Dieses Objekt enthält weder die vollständigen Metadaten des Objekts noch dessen Inhalt

import boto3
from botocore.errorfactory import ClientError
def path_exists(path, bucket_name):
    """Check to see if an object exists on S3"""
    s3 = boto3.resource('s3')
    try:
        s3.ObjectSummary(bucket_name=bucket_name, key=path).load()
    except ClientError as e:
        if e.response['Error']['Code'] == "404":
            return False
        else:
            raise e
    return True

path_exists('path/to/file.html')

In ObjectSummary.load

Ruft s3.Client.head_object auf, um die Attribute der ObjectSummary-Ressource zu aktualisieren.

Dies zeigt, dass Sie ObjectSummary anstelle von Object verwenden können, wenn Sie get() nicht verwenden möchten. Die Funktion load() ruft das Objekt nicht ab, sondern nur die Zusammenfassung.

0
Veedka

Wenn Sie weniger als 1000 in einem Verzeichnis oder Bucket haben, können Sie einen Satz davon erhalten und nachprüfen, ob ein solcher Schlüssel in diesem Satz enthalten ist:

files_in_dir = {d['Key'].split('/')[-1] for d in s3_client.list_objects_v2(
Bucket='mybucket',
Prefix='my/dir').get('Contents') or []}

Dieser Code funktioniert auch, wenn my/dir nicht vorhanden ist.

http://boto3.readthedocs.io/de/latest/reference/services/s3.html#S3.Client.list_objects_v2

0

Hier ist eine Lösung, die für mich funktioniert. Eine Einschränkung ist, dass ich das genaue Format des Schlüssels im Voraus kenne und daher nur die einzelne Datei aufliste

import boto3

# The s3 base class to interact with S3
class S3(object):
  def __init__(self):
    self.s3_client = boto3.client('s3')

  def check_if_object_exists(self, s3_bucket, s3_key):
    response = self.s3_client.list_objects(
      Bucket = s3_bucket,
      Prefix = s3_key
      )
    if 'ETag' in str(response):
      return True
    else:
      return False

if __== '__main__':
  s3  = S3()
  if s3.check_if_object_exists(bucket, key):
    print "Found S3 object."
  else:
    print "No object found."
0
Rush S

Sie können S3Fs verwenden. Dies ist im Wesentlichen ein Wrapper um boto3, der typische Operationen im Dateisystemstil verfügbar macht:

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

Ich habe festgestellt, dass wir, um die Ausnahme mit botocore.exceptions.ClientError zu erfassen, botocore installieren müssen. Botocore benötigt 36 MB Speicherplatz. Dies wirkt sich besonders aus, wenn wir aws-Lambda-Funktionen verwenden. Anstelle dessen, wenn wir nur eine Ausnahme verwenden, können wir die zusätzliche Bibliothek überspringen!

  • Ich bestätige, dass die Dateierweiterung '.csv' ist.
  • Dies wird keine Ausnahme auslösen, wenn der Bucket nicht existiert!
  • Es wird keine Ausnahme ausgelöst, wenn der Bucket vorhanden ist, das Objekt jedoch nicht vorhanden ist!
  • Dies gibt eine Ausnahme aus, wenn der Eimer leer ist!
  • Dies gibt eine Ausnahme aus, wenn der Bucket keine Berechtigungen hat!

Der Code sieht so aus. Bitte teile deine Gedanken mit:

import boto3
import traceback

def download4mS3(s3bucket, s3Path, localPath):
    s3 = boto3.resource('s3')

    print('Looking for the csv data file ending with .csv in bucket: ' + s3bucket + ' path: ' + s3Path)
    if s3Path.endswith('.csv') and s3Path != '':
        try:
            s3.Bucket(s3bucket).download_file(s3Path, localPath)
        except Exception as e:
            print(e)
            print(traceback.format_exc())
            if e.response['Error']['Code'] == "404":
                print("Downloading the file from: [", s3Path, "] failed")
                exit(12)
            else:
                raise
        print("Downloading the file from: [", s3Path, "] succeeded")
    else:
        print("csv file not found in in : [", s3Path, "]")
        exit(12)
0
user 923227
S3_REGION="eu-central-1"
bucket="mybucket1"
name="objectname"

import boto3
from botocore.client import Config
client = boto3.client('s3',region_name=S3_REGION,config=Config(signature_version='s3v4'))
list = client.list_objects_v2(Bucket=bucket,Prefix=name)
for obj in list.get('Contents', []):
    if obj['Key'] == name: return True
return False
0
jms

Wenn Sie einen Schlüssel suchen, der einem Verzeichnis entspricht, möchten Sie möglicherweise diesen Ansatz

session = boto3.session.Session()
resource = session.resource("s3")
bucket = resource.Bucket('mybucket')

key = 'dir-like-or-file-like-key'
objects = [o for o in bucket.objects.filter(Prefix=key).limit(1)]    
has_key = len(objects) > 0

Dies funktioniert für einen übergeordneten Schlüssel oder einen Schlüssel, der einer Datei oder einem Schlüssel entspricht, der nicht vorhanden ist. Ich habe den oben genannten bevorzugten Ansatz ausprobiert und bei den übergeordneten Schlüsseln versagt.

0
Peter Kahn

Es gibt eine einfache Möglichkeit, um zu überprüfen, ob eine Datei im S3-Bucket existiert oder nicht. Wir brauchen hierfür keine Ausnahme

sesssion = boto3.Session(aws_access_key_id, aws_secret_access_key)
s3 = session.client('s3')

object_name = 'filename'
bucket = 'bucketname'
obj_status = s3.list_objects(Bucket = bucket, Prefix = object_name)
if obj_status.get('Contents'):
    print("File exists")
else:
    print("File does not exists")
0
Mahesh Mogal