Administración de memoria y límites

sys incluye varias funciones para comprender y controlar el uso de la memoria.

Recuentos de referencias

La implementación principal de Python (CPython) usa recuento de referencias y recolección de basura para la administración automática de memoria. Un objeto se marca automáticamente para ser recolectado cuando su recuento de referencia cae a cero. Para examinar el recuento de referencia de un objeto existente, usa getrefcount().

sys_getrefcount.py
import sys

one = []
print('At start         :', sys.getrefcount(one))

two = one

print('Second reference :', sys.getrefcount(one))

del two

print('After del        :', sys.getrefcount(one))

El valor informado es en realidad uno más alto de lo esperado porque hay una referencia temporal al objeto contenido por getrefcount().

$ python3 sys_getrefcount.py

At start         : 2
Second reference : 3
After del        : 2

Ver también

  • gc – Control the garbage collector via the functions exposed in gc.

Tamaño de un objeto

Saber cuántas referencias tiene un objeto puede ayudar a encontrar ciclos o una pérdida de memoria, pero no es suficiente para determinar qué objetos están consumiendo la mayoría de la memoria. Eso requiere conocimiento sobre cuán grandes son los objetos.

sys_getsizeof.py
import sys


class MyClass:
    pass


objects = [
    [], (), {}, 'c', 'string', b'bytes', 1, 2.3,
    MyClass, MyClass(),
]

for obj in objects:
    print('{:>10} : {}'.format(type(obj).__name__,
                               sys.getsizeof(obj)))

getsizeof() informa el tamaño de un objeto en bytes.

$ python3 sys_getsizeof.py

      list : 64
     tuple : 48
      dict : 240
       str : 50
       str : 55
     bytes : 38
       int : 28
     float : 24
      type : 1056
   MyClass : 56

El tamaño informado para una clase personalizada no incluye el tamaño de los valores de los atributos.

sys_getsizeof_object.py
import sys


class WithoutAttributes:
    pass


class WithAttributes:
    def __init__(self):
        self.a = 'a'
        self.b = 'b'
        return


without_attrs = WithoutAttributes()
print('WithoutAttributes:', sys.getsizeof(without_attrs))

with_attrs = WithAttributes()
print('WithAttributes:', sys.getsizeof(with_attrs))

Esto puede dar una falsa impresión de la cantidad de memoria que se consume.

$ python3 sys_getsizeof_object.py

WithoutAttributes: 56
WithAttributes: 56

Para una estimación más completa del espacio utilizado por una clase, proporciona un método __sizeof__() para calcular el valor agregando los tamaños de los atributos de un objeto.

sys_getsizeof_custom.py
import sys


class WithAttributes:
    def __init__(self):
        self.a = 'a'
        self.b = 'b'
        return

    def __sizeof__(self):
        return object.__sizeof__(self) + \
            sum(sys.getsizeof(v) for v in self.__dict__.values())


my_inst = WithAttributes()
print(sys.getsizeof(my_inst))

Esta versión agrega el tamaño base del objeto a los tamaños de todos los atributos almacenados en el __dict__ interno.

$ python3 sys_getsizeof_custom.py

156

Recursión

Permitir una recursión infinita en una aplicación de Python puede introducir un desbordamiento de pila en el propio intérprete, lo que puede provocar un bloqueo. Para eliminar esta situación, el intérprete proporciona una forma de controlar la profundidad máxima de recursión usando setrecursionlimit() y getrecursionlimit().

sys_recursionlimit.py
import sys

print('Initial limit:', sys.getrecursionlimit())

sys.setrecursionlimit(10)

print('Modified limit:', sys.getrecursionlimit())


def generate_recursion_error(i):
    print('generate_recursion_error({})'.format(i))
    generate_recursion_error(i + 1)


try:
    generate_recursion_error(1)
except RuntimeError as err:
    print('Caught exception:', err)

Una vez que el tamaño de la pila alcanza el límite de recursividad, el intérprete genera una excepción RuntimeError para que el programa tenga la oportunidad de manejar la situación.

$ python3 sys_recursionlimit.py

Initial limit: 1000
Modified limit: 10
generate_recursion_error(1)
generate_recursion_error(2)
generate_recursion_error(3)
generate_recursion_error(4)
generate_recursion_error(5)
generate_recursion_error(6)
generate_recursion_error(7)
generate_recursion_error(8)
Caught exception: maximum recursion depth exceeded while calling
a Python object

Valores máximos

Junto con los valores configurables de tiempo de ejecución, sys incluye variables que definen los valores máximos para los tipos que varían de un sistema a otro.

sys_maximums.py
import sys

print('maxsize   :', sys.maxsize)
print('maxunicode:', sys.maxunicode)

maxsize es el tamaño máximo de una lista, diccionario, cadena u otra estructura de datos dictada por el tipo de tamaño del intérprete C. maxunicode es el punto entero Unicode más grande admitido por el intérprete como está configurado actualmente.

$ python3 sys_maximums.py

maxsize   : 9223372036854775807
maxunicode: 1114111

Valores de coma flotante

La estructura float_info contiene información sobre la representación de tipo de coma flotante utilizada por el intérprete, basada en la implementación del sistema subyacente float.

sys_float_info.py
import sys

print('Smallest difference (epsilon):', sys.float_info.epsilon)
print()
print('Digits (dig)              :', sys.float_info.dig)
print('Mantissa digits (mant_dig):', sys.float_info.mant_dig)
print()
print('Maximum (max):', sys.float_info.max)
print('Minimum (min):', sys.float_info.min)
print()
print('Radix of exponents (radix):', sys.float_info.radix)
print()
print('Maximum exponent for radix (max_exp):',
      sys.float_info.max_exp)
print('Minimum exponent for radix (min_exp):',
      sys.float_info.min_exp)
print()
print('Max. exponent power of 10 (max_10_exp):',
      sys.float_info.max_10_exp)
print('Min. exponent power of 10 (min_10_exp):',
      sys.float_info.min_10_exp)
print()
print('Rounding for addition (rounds):', sys.float_info.rounds)

Estos valores dependen del compilador y del sistema subyacente. Estos ejemplos se produjeron en OS X 10.9.5 en un Intel Core i7.

$ python3 sys_float_info.py

Smallest difference (epsilon): 2.220446049250313e-16

Digits (dig)              : 15
Mantissa digits (mant_dig): 53

Maximum (max): 1.7976931348623157e+308
Minimum (min): 2.2250738585072014e-308

Radix of exponents (radix): 2

Maximum exponent for radix (max_exp): 1024
Minimum exponent for radix (min_exp): -1021

Max. exponent power of 10 (max_10_exp): 308
Min. exponent power of 10 (min_10_exp): -307

Rounding for addition (rounds): 1

Ver también

  • El archivo de encabezado C float.h para el compilador local contiene más detalles sobre esta configuración.

Valores enteros

La estructura int_info contiene información sobre la representación interna de los enteros utilizados por el intérprete.

sys_int_info.py
import sys

print('Number of bits used to hold each digit:',
      sys.int_info.bits_per_digit)
print('Size in bytes of C type used to hold each digit:',
      sys.int_info.sizeof_digit)

Estos ejemplos se produjeron en OS X 10.9.5 en un Intel Core i7.

$ python3 sys_int_info.py

Number of bits used to hold each digit: 30
Size in bytes of C type used to hold each digit: 4

El tipo C utilizado para almacenar enteros internamente se determina cuando se construye el intérprete. Las arquitecturas de 64 bits usan automáticamente enteros de 30 bits de forma predeterminada, y pueden habilitarse para arquitecturas de 32 bits con el indicador de configuración --enable-big-digits.

Ver también

Orden de bytes

byteorder se establece en el orden de bytes nativo.

sys_byteorder.py
import sys

print(sys.byteorder)

El valor es big para big-endian o little para little-endian.

$ python3 sys_byteorder.py

little

Ver también

  • Wikipedia: Endianness – Descripción del formato en el que se almacenan los datos de más de un byte en un ordenador.
  • array y struct – Otros módulos que dependen del orden de bytes de los datos.
  • float.h – El archivo de encabezado C para el compilador local contiene más detalles sobre esta configuración.