проверьте, существует ли ключ в ведре в s3 с помощью boto3
Я хотел бы знать, существует ли ключ в boto3. Я могу зациклить содержимое ведра и проверить ключ, если он соответствует.
но это, кажется, уже и перебор. Официальные документы Boto3 явно указывают, как это сделать.
может быть, я упускаю очевидное. Может ли кто-нибудь указать мне, как я могу этого достичь.
11 ответов:
Boto 2's
boto.s3.key.Key
объект, используемый, чтобы иметьexists
метод, который проверил, существует ли ключ на S3, выполнив запрос HEAD и посмотрев на результат, но кажется, что он больше не существует. Вы должны сделать это сами: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()
делает запрос головы для одного ключа, который является быстрым, даже если объект в вопросе большой или у вас есть много объектов в вашем ведре.конечно, вы можете проверить, существует ли объект, потому что вы планируете использующий ее. Если это так, вы можете просто забыть об
load()
иget()
илиdownload_file()
непосредственно, а затем обрабатывать случай ошибки там.
Я не большой поклонник использования исключений для потока управления. Это альтернативный подход, который работает в 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")
самый простой способ, который я нашел (и, вероятно, самый эффективный) это:
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
в Boto3, если вы проверяете папку (префикс) или файл с помощью list_objects. Вы можете использовать существование "содержимого" в ответе dict в качестве проверки того, существует ли объект. Это еще один способ избежать try / except catches, как предлагает @EvilPuppetMaster
import boto3 client = boto3.client('s3') results = client.list_objects(Bucket='my-bucket', Prefix='dootdoot.jpg') return 'Contents' in results
не только
client
но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')
есть один простой способ, с помощью которого мы можем проверить, существует ли файл или нет в ведре S3. Нам не нужно использовать исключение для этого
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")
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)
Если у вас меньше 1000 в каталоге или ведра можно установить их и после проверки, если такой ключ в этом наборе:
files_in_dir = {d['Key'].split('/')[-1] for d in s3_client.list_objects_v2( Bucket='mybucket', Prefix='my/dir').get('Contents') or []}
такой код работает, даже если
my/dir
не существует.http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.list_objects_v2
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
FWIW, вот очень простые функции, которые я использую
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
проверить
bucket.get_key( key_name, headers=None, version_id=None, response_headers=None, validate=True )
проверьте, существует ли определенный ключ в ведре. Этот метод использует запрос HEAD для проверки наличия ключа. Возвращает: В экземпляр ключевого объекта или нет
вы можете просто позвонить в ведро.get_key (keyname) и проверьте, является ли возвращаемый объект None.