compruebe si existe una clave en un bucket en s3 usando boto3
Me gustaría saber si existe una clave en boto3. Puedo hacer un bucle en el contenido del cubo y comprobar la llave si coincide.
Pero eso parece más largo y excesivo. Los documentos oficiales de Boto3 indican explícitamente cómo hacerlo.
Puede ser que me esté perdiendo lo obvio. ¿Puede alguien indicarme cómo puedo lograr esto?
11 answers
El objeto boto.s3.key.Key
de Boto 2 solía tener un método exists
que verificaba si la clave existía en S3 haciendo una petición HEAD y mirando el resultado, pero parece que ya no existe. Tienes que hacerlo tú mismo:
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()
hace una solicitud de CABEZA para una sola clave, que es rápida, incluso si el objeto en cuestión es grande o tiene muchos objetos en su cubo.
Por supuesto, es posible que esté comprobando si el objeto existe porque está planeando usarlo. Si ese es el caso, usted puede simplemente olvidarse de la load()
y hacer un get()
o download_file()
directamente, a continuación, manejar el caso de error allí.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-08 18:09:00
No soy un gran fan de usar excepciones para controlar el flujo. Este es un enfoque alternativo que funciona en 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")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-08 02:11:42
La forma más fácil que encontré (y probablemente la más eficiente) es esta:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-21 00:45:40
En Boto3, si está buscando una carpeta (prefijo) o un archivo usando list_objects. Puede utilizar la existencia de 'Contenidos' en el diccionario de respuesta como una comprobación de si el objeto existe. Es otra forma de evitar las capturas try / except como sugiere @EvilPuppetMaster
import boto3
client = boto3.client('s3')
results = client.list_objects(Bucket='my-bucket', Prefix='dootdoot.jpg')
return 'Contents' in results
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-12 14:49:29
No solo client
sino bucket
también:
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')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-14 15:33:37
Hay una manera simple por la cual podemos comprobar si el archivo existe o no en el bucket S3. No necesitamos usar excepción para esto
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")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-05 08:12:30
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-10 18:23:47
Si tiene menos de 1000 en un directorio o cubo, puede obtener un conjunto de ellos y después verificar si dicha clave en este conjunto:
files_in_dir = {d['Key'].split('/')[-1] for d in s3_client.list_objects_v2(
Bucket='mybucket',
Prefix='my/dir').get('Contents') or []}
Dicho código funciona incluso si my/dir
no existe.
Http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.list_objects_v2
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-14 18:33:51
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-23 12:15:00
FWIW, aquí están las funciones muy simples que estoy usando
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-06 21:07:21
Echa un vistazo
bucket.get_key(
key_name,
headers=None,
version_id=None,
response_headers=None,
validate=True
)
Compruebe si existe una clave en particular dentro del bucket. Este método utiliza una petición HEAD para comprobar la existencia de la clave. Devoluciones: An instancia de un objeto Clave o None
De Boto S3 Docs
Puedes llamar a bucket.get_key (keyname) y compruebe si el objeto devuelto es None.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-02 19:56:22