Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

338
Views
Heroku web dyno ejecutando la aplicación Django sin liberar memoria

Estoy luchando con un problema de memoria en Heroku cuando ejecuto una aplicación Django (con gunicorn).

Tengo el siguiente código que toma una imagen cargada por el usuario, elimina todos los datos EXIF y devuelve la imagen lista para cargarla en S3. Esto se usa como un limpiador de datos de formulario y al leer datos base64 en la memoria.

 def sanitise_image(img): # img is InMemoryUploadedFile try: image = Image.open(img) except IOError: return None # Move all pixel data into a new PIL image data = list(image.getdata()) image_without_exif = Image.new(image.mode, image.size) image_without_exif.putdata(data) # Create new file with image_without_exif instead of input image. thumb_io = StringIO.StringIO() image_without_exif.save(thumb_io, format=image.format) io_len = thumb_io.len thumb_file = InMemoryUploadedFile(thumb_io, None, strip_tags(img.name), img.content_type, io_len, None) # DEL AND CLOSE EVERYTHING thumb_file.seek(0) img.close() del img thumb_io.close() image_without_exif.close() del image_without_exif image.close() del image return thumb_file

Básicamente tomo un InMemoryUploadedFile y devuelvo uno nuevo con solo los datos de píxeles.

del y close s pueden ser redundantes, pero representan mi intento de solucionar la situación en la que el uso de la memoria de Heroku sigue creciendo y no se libera cada vez que esta función finaliza, incluso permaneciendo durante la noche: Métricas de Heroku

Ejecutando esto en localhost con Guppy y siguiendo el tutorial, no quedan InMemoryUploadedFile s ni StringIO s ni PIL Image en el montón, lo que me deja desconcertado.

Mi sospecha es que Python no libera la memoria al sistema operativo, como he leído en varios hilos en SO. ¿Alguien ha jugado con InMemoryUploadedFile y puede darme una explicación de por qué esta memoria no se libera?

Cuando no realizo esta desinfección, el problema no ocurre.

¡Muchas gracias!

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Creo que el problema es crear el objeto de lista temporal:

 data = list(image.getdata())

Probar:

 image_without_exif.putdata(image.getdata())


Por eso creo que ese es el problema:

 >>> images = [Image.new('RGBA', (100, 100)) for _ in range(100)]

El uso de la memoria de Python aumentó ~4Mb.

 >>> get_datas = [image.getdata() for image in images]

Sin aumento de memoria.

 >>> pixel_lists = [list(image.getdata()) for image in images]

El uso de la memoria de Python aumentó en ~ 85 Mb.


Probablemente no quiera convertir getdata() en una lista a menos que necesite los números explícitamente. De los documentos de Pillow:

Tenga en cuenta que el objeto de secuencia devuelto por este método es un tipo de datos PIL interno, que solo admite ciertas operaciones de secuencia. Para convertirlo en una secuencia ordinaria (por ejemplo, para imprimir), use list(im.getdata()).

over 4 years ago · Santiago Trujillo Report

0

Eventualmente encontré mi propia respuesta. Muchas gracias a Ryan Tran por indicarme la dirección correcta. list() de hecho causa la fuga.

Usando el método equivalente split() y merge() ( docs ), este es el código actualizado:

 with Image.open(img) as image: comp = image.split() image_without_exif = Image.merge(image.mode, comp) thumb_io = StringIO.StringIO() image_without_exif.save(thumb_io, format=image.format) io_len = thumb_io.len clean_img = InMemoryUploadedFile(thumb_io, None, strip_tags(img.name), img.content_type, io_len, None) clean_img.seek(0) return clean_img
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!