Otras respuestas en este hilo están relacionadas con boto, pero S3.Object ya no es iterable en boto3. Por lo tanto, el siguiente no funciona, se produce un mensaje de TypeError: 's3.Object' object is not iterable
error:
s3 = boto3.session.Session(profile_name=my_profile).resource('s3')
s3_obj = s3.Object(bucket_name=my_bucket, key=my_key)
with io.FileIO('sample.txt', 'w') as file:
for i in s3_obj:
file.write(i)
En boto3, el contenido del objeto está disponible en S3.Object.get()['Body']
que no es un iterable tampoco, por lo que el siguiente no funciona:
body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for i in body:
file.write(i)
por lo tanto, una alternativa es utilizar el método de lectura, pero esta carga el objeto S3 TODO en la memoria, que cuando se trata de archivos de gran tamaño no es siempre una posibilidad:
body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for i in body.read():
file.write(i)
Pero el método read
permite pasar el parámetro amt
que especifica el número de bytes que queremos leer de la secuencia subyacente. Este método puede ser llamado varias veces hasta que toda la corriente ha sido leída:
body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
while file.write(body.read(amt=512)):
pass
Excavando en botocore.response.StreamingBody
código uno se da cuenta de que la secuencia subyacente también está disponible, por lo que podría repetir la siguiente manera:
body = s3_obj.get()['Body']
with io.FileIO('sample.txt', 'w') as file:
for b in body._raw_stream:
file.write(b)
Mientras googlear también he visto algunos enlaces que podrían ser el uso, pero no lo he probado:
El [smart_open] (https://github.com/piskvorky/smart_open) biblioteca Python hace eso (tanto para leer como para escribir). – Radim