Quiero saber cómo obtener el tamaño de los objetos como una cadena, un entero, etc. en Python.
Pregunta relacionada: ¿Cuántos bytes por elemento hay en una lista de Python (tupla)?
Estoy usando un archivo XML que contiene campos de tamaño que especifican el tamaño del valor. Debo analizar este XML y hacer mi codificación. Cuando quiero cambiar el valor de un campo en particular, comprobaré el campo de tamaño de ese valor. Aquí quiero comparar si el nuevo valor que voy a ingresar es del mismo tamaño que en XML. Necesito verificar el tamaño del nuevo valor. En caso de una cadena, puedo decir que es la longitud. Pero en caso de int, float, etc. Estoy confundido.
__sizeof__
método para su clase. Ladict
clase python incorporada lo define, es por eso que obtienes el resultado correcto cuando usas un objeto de tipodict
.getsizeof
función de poco valor fuera de la caja.La respuesta, "Solo use sys.getsizeof" no es una respuesta completa.
Esa respuesta hace el trabajo de orden interna se opone directamente, pero no tiene en cuenta lo que esos objetos pueden contener, en concreto, qué tipos, tales como objetos personalizados, tuplas, listas, predice y conjuntos contienen. Pueden contener instancias entre sí, así como números, cadenas y otros objetos.
Una respuesta más completa
Utilizando Python 3.6 de 64 bits de la distribución Anaconda, con sys.getsizeof, he determinado el tamaño mínimo de los siguientes objetos, y noto que los conjuntos y los dictos preasignan el espacio para que los vacíos no vuelvan a crecer hasta después de una cantidad establecida (que puede variar según la implementación del idioma):
Python 3:
como interpretas esto? Bueno, digamos que tienes un conjunto con 10 elementos. Si cada elemento tiene 100 bytes cada uno, ¿qué tan grande es la estructura de datos completa? El conjunto es 736 en sí porque se ha dimensionado una vez a 736 bytes. Luego agrega el tamaño de los elementos, por lo que son 1736 bytes en total
Algunas advertencias para las definiciones de función y clase:
Tenga en cuenta que cada definición de clase tiene una
__dict__
estructura proxy (48 bytes) para los atributos de clase. Cada ranura tiene un descriptor (como aproperty
) en la definición de clase.Las instancias ranuradas comienzan con 48 bytes en su primer elemento y aumentan en 8 cada una adicional. Solo los objetos ranurados vacíos tienen 16 bytes, y una instancia sin datos tiene muy poco sentido.
Además, cada definición de función tiene objetos de código, tal vez cadenas de documentos y otros posibles atributos, incluso a
__dict__
.También tenga en cuenta que usamos
sys.getsizeof()
porque nos importa el uso del espacio marginal, que incluye la sobrecarga de recolección de basura para el objeto, de los documentos :También tenga en cuenta que cambiar el tamaño de las listas (por ejemplo, agregarlas repetidamente) hace que preasignen espacio, de manera similar a los conjuntos y los dictados. Del código fuente listobj.c :
Información histórica
Análisis de Python 2.7, confirmado con
guppy.hpy
ysys.getsizeof
:Tenga en cuenta que los diccionarios ( pero no los conjuntos ) tienen una representación más compacta en Python 3.6
Creo que 8 bytes por elemento adicional de referencia tiene mucho sentido en una máquina de 64 bits. Esos 8 bytes apuntan al lugar en la memoria donde está el elemento contenido. Los 4 bytes son de ancho fijo para Unicode en Python 2, si recuerdo correctamente, pero en Python 3, str se convierte en un Unicode de ancho igual al ancho máximo de los caracteres.
(Y para más información sobre tragamonedas, vea esta respuesta )
Una función más completa
Queremos una función que busque los elementos en listas, tuplas, conjuntos, dictos,
obj.__dict__
's' yobj.__slots__
otras cosas en las que aún no hemos pensado.Queremos confiar en
gc.get_referents
hacer esta búsqueda porque funciona en el nivel C (lo que lo hace muy rápido). La desventaja es que get_referents puede devolver miembros redundantes, por lo que debemos asegurarnos de no contar dos veces.Las clases, los módulos y las funciones son singletons: existen una vez en la memoria. No estamos tan interesados en su tamaño, ya que no hay mucho que podamos hacer al respecto, son parte del programa. Así que evitaremos contarlos si se hace referencia a ellos.
Vamos a utilizar una lista negra de tipos para no incluir todo el programa en nuestro recuento de tamaños.
Para contrastar esto con la siguiente función incluida en la lista blanca, la mayoría de los objetos saben cómo atravesarse para la recolección de basura (que es aproximadamente lo que estamos buscando cuando queremos saber qué tan caros en memoria son ciertos objetos. Esta funcionalidad es utilizada por
gc.get_referents
.) Sin embargo, esta medida tendrá un alcance mucho más amplio de lo que pretendíamos si no tenemos cuidado.Por ejemplo, las funciones saben bastante sobre los módulos en los que se crean.
Otro punto de contraste es que las cadenas que son claves en los diccionarios generalmente están internadas para que no se dupliquen. La verificación
id(key)
también nos permitirá evitar contar duplicados, lo que hacemos en la siguiente sección. La solución de la lista negra omite las teclas de conteo que son cadenas por completo.Tipos incluidos en la lista blanca, visitante recursivo (implementación anterior)
Para cubrir la mayoría de estos tipos, en lugar de depender del módulo gc, escribí esta función recursiva para tratar de estimar el tamaño de la mayoría de los objetos de Python, incluidos la mayoría de los elementos incorporados, los tipos en el módulo de colecciones y los tipos personalizados (ranurado y de otro modo) .
Este tipo de función proporciona un control mucho más detallado sobre los tipos que vamos a contar para el uso de la memoria, pero tiene el peligro de omitir los tipos:
Y lo probé de manera bastante informal (debería probarlo unitariamente):
Esta implementación desglosa las definiciones de clase y las definiciones de función porque no buscamos todos sus atributos, pero dado que solo deberían existir una vez en la memoria para el proceso, su tamaño realmente no importa demasiado.
fuente
El módulo del paquete Pympler
asizeof
puede hacer esto.Use de la siguiente manera:
A diferencia
sys.getsizeof
, funciona para tus objetos creados por ti mismo . Incluso funciona con numpy.Como se mencionó ,
Y si necesita otra vista de datos en vivo, Pympler's
fuente
org.apache.spark.util.SizeEstimator
puede ser relevantepympler
tiene la capacidad de tener en cuenta el tamaño del código ejecutable de las funciones y otras llamadas y objetos de código.TypeError
excepción: "el objeto 'NoneType' no es invocable" cada vez que mi objeto personalizado tiene algún subobjeto en su "árbol" con valorNone
. ¿Hay alguna solución rápida para esto?Para matrices numpy,
getsizeof
no funciona, para mí siempre devuelve 40 por alguna razón:Entonces (en ipython):
Felizmente, sin embargo:
fuente
getsizeof()
solo le da el tamaño del objeto (el encabezado de la matriz), no de los datos que contiene. Lo mismo para los contenedores de python dondesys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48
, mientras quesys.getsizeof(123**456) = 436
getsizeof()
función se cambió en algún momento para devolver el valor esperado.Esto puede ser más complicado de lo que parece dependiendo de cómo desee contar las cosas. Por ejemplo, si tiene una lista de entradas, ¿desea el tamaño de la lista que contiene las referencias a las entradas? (es decir, solo una lista, no lo que contiene), o desea incluir los datos reales señalados, en cuyo caso debe tratar con referencias duplicadas y cómo evitar el doble recuento cuando dos objetos contienen referencias a El mismo objeto.
Es posible que desee echar un vistazo a uno de los perfiladores de memoria de Python, como pysizer, para ver si satisfacen sus necesidades.
fuente
Python 3.8 (Q1 2019) cambiará algunos de los resultados de
sys.getsizeof
, según lo anunciado por Raymond Hettinger:Esto viene después del problema 33597 y el trabajo de Inada Naoki (
methane
) en torno a Compact PyGC_Head y PR 7043Ver commit d5c875b :
fuente
Habiendo encontrado este problema muchas veces, escribí una pequeña función (inspirada en la respuesta de @ aaron-hall) y pruebas que hacen lo que esperaba que hiciera sys.getsizeof:
https://github.com/bosswissam/pysize
Si estás interesado en la historia de fondo, aquí está
EDITAR: Adjuntando el siguiente código para una fácil referencia. Para ver el código más actualizado, consulte el enlace de github.
fuente
Aquí hay un script rápido que escribí basado en las respuestas anteriores para enumerar los tamaños de todas las variables
fuente
Puede serializar el objeto para derivar una medida que esté estrechamente relacionada con el tamaño del objeto:
Si desea medir objetos que no se pueden encurtir (por ejemplo, debido a expresiones lambda), cloudpickle puede ser una solución.
fuente
Use sys.getsizeof () si NO desea incluir tamaños de objetos vinculados (anidados).
Sin embargo, si desea contar los subobjetos anidados en listas, dictados, conjuntos, tuplas, y generalmente ESTO es lo que está buscando, use la función recursiva deep sizeof () como se muestra a continuación:
También puede encontrar esta función en la ingeniosa caja de herramientas, junto con muchas otras frases útiles útiles:
https://github.com/mwojnars/nifty/blob/master/util.py
fuente
Si no necesita el tamaño exacto del objeto, pero aproximadamente para saber qué tan grande es, una forma rápida (y sucia) es dejar que el programa se ejecute, dormir durante un período prolongado de tiempo y verificar el uso de la memoria (ej. : Monitor de actividad de Mac) por este proceso particular de Python. Esto sería efectivo cuando intente encontrar el tamaño de un solo objeto grande en un proceso de Python. Por ejemplo, recientemente quería verificar el uso de la memoria de una nueva estructura de datos y compararlo con el de la estructura de datos establecida de Python. Primero escribí los elementos (palabras de un gran libro de dominio público) en un conjunto, luego verifiqué el tamaño del proceso y luego hice lo mismo con la otra estructura de datos. Descubrí que el proceso de Python con un conjunto está tomando el doble de memoria que la nueva estructura de datos. De nuevo, no lo harías No podrá decir exactamente que la memoria utilizada por el proceso es igual al tamaño del objeto. A medida que el tamaño del objeto aumenta, esto se reduce a medida que la memoria consumida por el resto del proceso se vuelve insignificante en comparación con el tamaño del objeto que está tratando de monitorear.
fuente
Puede utilizar getSizeof () como se menciona a continuación para determinar el tamaño de un objeto
fuente
Utilizo este truco ... May no será preciso en objetos pequeños, pero creo que es mucho más preciso para un objeto complejo (como la superficie de un juego de cartas) en lugar de sys.getsizeof ()
En mi Windows 10, Python 3.7.3, el resultado es:
fuente