J'aimerais savoir s'il existe une clé dans boto3. Je peux boucler le contenu du seau et vérifier la clé si elle correspond.
Mais cela semble plus long et exagéré. La documentation officielle de Boto3 indique explicitement comment procéder.
Peut-être que je manque l'évidence. Quelqu'un peut-il me dire comment je peux y arriver?.
L’objet boto.s3.key.Key
de Boto 2 avait une méthode exists
qui vérifiait si la clé existait sur S3 en faisant une requête HEAD et en regardant le résultat, mais il semble que cela n’existe plus. Vous devez le faire vous-même:
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()
effectue une demande HEAD pour une clé unique, ce qui est rapide, même si l'objet en question est volumineux ou si vous avez plusieurs objets dans votre compartiment.
Bien sûr, vous pouvez vérifier si l'objet existe parce que vous prévoyez de l'utiliser. Si tel est le cas, vous pouvez simplement oublier la fonction load()
et effectuer directement une fonction get()
ou download_file()
, puis gérer le cas d'erreur à cet endroit.
Je ne suis pas un grand fan de l'utilisation des exceptions pour le contrôle du flux. C'est une approche alternative qui fonctionne dans boto3:
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")
Le moyen le plus simple que j'ai trouvé (et probablement le plus efficace) est le suivant:
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
Dans Boto3, si vous recherchez un dossier (préfixe) ou un fichier utilisant list_objects. Vous pouvez utiliser l'existence de 'Contenu' dans le dict de réponse pour vérifier si l'objet existe ou non. C'est une autre façon d'éviter les tentatives try/except, comme le suggère @EvilPuppetMaster.
import boto3
client = boto3.client('s3')
results = client.list_objects(Bucket='my-bucket', Prefix='dootdoot.jpg')
return 'Contents' in results
Non seulement client
, mais aussi 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')
Essayez ceci simple
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")
FWIW, voici les fonctions très simples que j'utilise
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
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)
Pour boto3, ObjectSummary peut être utilisé pour vérifier si un objet existe.
Contient le récapitulatif d'un objet stocké dans un compartiment Amazon S3. Cet objet ne contient pas les métadonnées complètes de l'objet, ni aucun de ses contenus.
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')
Dans ObjectSummary.load
Appelle s3.Client.head_object pour mettre à jour les attributs de la ressource ObjectSummary.
Cela montre que vous pouvez utiliser ObjectSummary
au lieu de Object
si vous prévoyez de ne pas utiliser get()
. La fonction load()
ne récupère pas l'objet, elle obtient uniquement le résumé.
Si vous avez moins de 1000 dans un répertoire ou un compartiment, vous pouvez en obtenir un et vérifier après si cette clé est dans cet ensemble:
files_in_dir = {d['Key'].split('/')[-1] for d in s3_client.list_objects_v2(
Bucket='mybucket',
Prefix='my/dir').get('Contents') or []}
Ce code fonctionne même si my/dir
n'existe pas.
http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.list_objects_v2
Voici une solution qui fonctionne pour moi. Une mise en garde est que je connais le format exact de la clé à l’avance, je ne fais donc que lister le fichier unique.
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."
Vous pouvez utiliser S3Fs , qui est essentiellement un wrapper autour de boto3 qui expose les opérations de style de système de fichiers typiques:
import s3fs
s3 = s3fs.S3FileSystem()
s3.exists('myfile.txt')
J'ai remarqué que pour attraper l'exception à l'aide de botocore.exceptions.ClientError
, nous devons installer botocore. botocore occupe 36M d’espace disque. Ceci est particulièrement important si nous utilisons les fonctions aws lambda. Au lieu de cela, si nous utilisons simplement une exception, nous pouvons sauter en utilisant la bibliothèque supplémentaire!
Le code ressemble à ceci. S'il vous plaît partager vos pensées:
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)
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
Si vous recherchez une clé équivalente à un répertoire, vous souhaiterez peut-être cette approche.
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
Cela fonctionne pour une clé parent ou une clé qui équivaut à un fichier ou une clé qui n'existe pas. J'ai essayé l'approche privilégiée ci-dessus et j'ai échoué sur les clés parent.
Il existe un moyen simple de vérifier si le fichier existe ou non dans le compartiment S3. Nous n'avons pas besoin d'utiliser l'exception pour cela
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")