Eu quero saber como obter o tamanho de objetos como uma seqüência de caracteres, número inteiro, etc. em Python.
Pergunta relacionada: Quantos bytes por elemento existem em uma lista Python (tupla)?
Estou usando um arquivo XML que contém campos de tamanho que especificam o tamanho do valor. Eu devo analisar esse XML e fazer minha codificação. Quando quiser alterar o valor de um campo específico, verificarei o campo de tamanho desse valor. Aqui, quero comparar se o novo valor que devo inserir é do mesmo tamanho que no XML. Preciso verificar o tamanho do novo valor. No caso de uma string, posso dizer que é o comprimento. Mas no caso de int, float etc. estou confuso.
__sizeof__
método para sua classe. Adict
classe python interna o define, é por isso que você obtém o resultado correto ao usar o objeto do tipodict
.getsizeof
função de pouco valor pronta para uso.A resposta "Apenas use sys.getsizeof" não é uma resposta completa.
Essa resposta faz trabalho para builtin objetos diretamente, mas não leva em conta o que esses objetos podem conter, especificamente, quais os tipos, tais como objetos personalizados, tuplas, listas, dicts e conjuntos contêm. Eles podem conter instâncias um do outro, além de números, seqüências de caracteres e outros objetos.
Uma resposta mais completa
Usando o Python 3.6 de 64 bits da distribuição Anaconda, com sys.getsizeof, determinei o tamanho mínimo dos seguintes objetos e observe que os conjuntos e os dicionários pré-alocam espaço para que os vazios não cresçam novamente até depois de um determinado valor (o que pode variar de acordo com a implementação do idioma):
Python 3:
Como você interpreta isso? Bem, digamos que você tenha um conjunto com 10 itens. Se cada item tem 100 bytes cada, qual é o tamanho de toda a estrutura de dados? O conjunto é o próprio 736 porque foi dimensionado uma vez para 736 bytes. Então você adiciona o tamanho dos itens, totalizando 1736 bytes
Algumas advertências para definições de função e classe:
Observe que cada definição de classe possui uma estrutura de proxy
__dict__
(48 bytes) para atributos de classe. Cada slot possui um descritor (como aproperty
) na definição de classe.Instâncias com slot começam com 48 bytes no primeiro elemento e aumentam em 8 a cada adicional. Somente objetos com espaço vazio têm 16 bytes, e uma instância sem dados faz muito pouco sentido.
Além disso, cada definição de função possui objetos de código, talvez docstrings e outros atributos possíveis, até a
__dict__
.Observe também que usamos
sys.getsizeof()
porque nos preocupamos com o uso do espaço marginal, que inclui a sobrecarga da coleta de lixo para o objeto, nos documentos :Observe também que o redimensionamento de listas (por exemplo, anexando-as repetidamente) faz com que pré-alocem espaço, da mesma forma que sets e dict. A partir do código-fonte listobj.c :
Data histórica
Análise do Python 2.7, confirmada com
guppy.hpy
esys.getsizeof
:Observe que os dicionários ( mas não os conjuntos ) obtiveram uma representação mais compacta no Python 3.6
Eu acho que 8 bytes por item adicional para referência faz muito sentido em uma máquina de 64 bits. Esses 8 bytes apontam para o local na memória em que o item contido está. Os 4 bytes têm largura fixa para unicode no Python 2, se bem me lembro, mas no Python 3, str se torna um unicode de largura igual à largura máxima dos caracteres.
(E para saber mais sobre slots, veja esta resposta )
Uma função mais completa
Queremos uma função que pesquise os elementos em listas, tuplas, conjuntos, ditados,
obj.__dict__
's eobj.__slots__
, além de outras coisas que talvez ainda não tenhamos pensado.Queremos contar
gc.get_referents
com essa pesquisa porque ela funciona no nível C (tornando-a muito rápida). A desvantagem é que get_referents pode retornar membros redundantes, portanto, precisamos garantir que não contemos duas vezes.Classes, módulos e funções são singletons - eles existem uma vez na memória. Não estamos tão interessados em seu tamanho, pois não há muito o que fazer sobre eles - eles fazem parte do programa. Portanto, evitaremos contá-los se eles forem referenciados.
Usaremos uma lista negra de tipos para não incluir o programa inteiro em nossa contagem de tamanhos.
Para contrastar isso com a seguinte função na lista de permissões, a maioria dos objetos sabe como se mover para fins de coleta de lixo (que é aproximadamente o que estamos procurando quando queremos saber o quão caro são na memória certos objetos. Essa funcionalidade é usada por
gc.get_referents
.) No entanto, essa medida terá um alcance muito mais amplo do que pretendíamos se não tomarmos cuidado.Por exemplo, as funções sabem bastante sobre os módulos em que são criadas.
Outro ponto de contraste é que as seqüências de caracteres que são chaves nos dicionários geralmente são internadas para que não sejam duplicadas. A verificação
id(key)
também permitirá evitar a contagem de duplicatas, o que faremos na próxima seção. A solução da lista negra ignora a contagem de chaves que são seqüências de caracteres por completo.Tipos de lista de permissões, visitante recursivo (implementação antiga)
Para cobrir a maioria desses tipos, em vez de depender do módulo gc, escrevi essa função recursiva para tentar estimar o tamanho da maioria dos objetos Python, incluindo a maioria dos componentes internos, tipos no módulo de coleções e tipos personalizados (com ou sem fenda) .
Esse tipo de função fornece muito mais controle refinado sobre os tipos que contaremos para uso de memória, mas tem o risco de deixar os tipos de fora:
E eu testei casualmente (eu deveria unittest):
Essa implementação divide-se nas definições de classe e nas definições de função porque não seguimos todos os seus atributos, mas como eles só devem existir uma vez na memória para o processo, seu tamanho realmente não importa muito.
fonte
O módulo do pacote Pympler
asizeof
pode fazer isso.Use da seguinte maneira:
Ao contrário
sys.getsizeof
, ele funciona para seus objetos criados automaticamente . Até funciona com numpy.Como mencionado ,
E se você precisar de outra visão sobre dados ao vivo, o Pympler
fonte
org.apache.spark.util.SizeEstimator
pode ser relevantepympler
possui recursos para levar em consideração o tamanho do código executável de funções e outros códigos de chamada e objetos de código.TypeError
exceção: "O objeto 'NoneType' não pode ser chamado" sempre que meu objeto personalizado tiver algum subobjeto em sua "árvore" com valorNone
. Existe alguma solução rápida para isso?Para matrizes numpy,
getsizeof
não funciona - para mim, sempre retorna 40 por algum motivo:Então (no ipython):
Felizmente, porém:
fonte
getsizeof()
apenas fornece o tamanho do objeto (o cabeçalho da matriz), não dos dados internos. Mesmo para recipientes python, ondesys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48
, ao mesmo temposys.getsizeof(123**456) = 436
getsizeof()
função foi alterada em algum momento para retornar o valor esperado.Isso pode ser mais complicado do que parece, dependendo de como você deseja contar as coisas. Por exemplo, se você possui uma lista de entradas, deseja o tamanho da lista que contém as referências às entradas? (ou seja, apenas lista, não o que está contido nela) ou você deseja incluir os dados reais apontados; nesse caso, você precisa lidar com referências duplicadas e como evitar a contagem dupla quando dois objetos contêm referências a o mesmo objeto.
Você pode dar uma olhada em um dos criadores de perfil de memória python, como o pysizer, para ver se eles atendem às suas necessidades.
fonte
O Python 3.8 (primeiro trimestre de 2019) mudará alguns dos resultados de
sys.getsizeof
, conforme anunciado aqui por Raymond Hettinger:Isso ocorre após a edição 33597 e o trabalho de Inada Naoki (
methane
) em torno do Compact PyGC_Head e PR 7043Consulte commit d5c875b :
fonte
Tendo encontrado esse problema muitas vezes, escrevi uma pequena função (inspirada na resposta de @ aaron-hall) e testes que fazem o que eu esperava que sys.getsizeof fizesse:
https://github.com/bosswissam/pysize
Se você está interessado na história de fundo, aqui está
EDIT: Anexando o código abaixo para fácil referência. Para ver o código mais atualizado, consulte o link do github.
fonte
Aqui está um script rápido que escrevi com base nas respostas anteriores para listar tamanhos de todas as variáveis
fonte
Você pode serializar o objeto para derivar uma medida que esteja intimamente relacionada ao tamanho do objeto:
Se você deseja medir objetos que não podem ser decapados (por exemplo, devido a expressões lambda), o cloudpickle pode ser uma solução.
fonte
Use sys.getsizeof () se você NÃO deseja incluir tamanhos de objetos vinculados (aninhados).
No entanto, se você quiser contar subobjetos aninhados em listas, dictos, conjuntos, tuplas - e geralmente ISSO é o que você está procurando - use a função sizeof () profunda recursiva, como mostrado abaixo:
Você também pode encontrar esta função na caixa de ferramentas bacana , junto com muitas outras opções úteis:
https://github.com/mwojnars/nifty/blob/master/util.py
fonte
Se você não precisar do tamanho exato do objeto, mas aproximadamente para saber o tamanho dele, uma maneira rápida (e suja) é deixar o programa funcionar, dormir por um longo período de tempo e verificar o uso da memória (ex. : Monitor de atividade do Mac) por esse processo python específico. Isso seria eficaz quando você estiver tentando encontrar o tamanho de um único objeto grande em um processo python. Por exemplo, recentemente eu queria verificar o uso da memória de uma nova estrutura de dados e compará-la com a da estrutura de dados do Python. Primeiro, escrevi os elementos (palavras de um grande livro de domínio público) em um conjunto, depois verifiquei o tamanho do processo e depois fiz a mesma coisa com a outra estrutura de dados. Descobri que o processo Python com um conjunto está consumindo o dobro de memória que a nova estrutura de dados. Mais uma vez, você não ser capaz de dizer exatamente que a memória usada pelo processo é igual ao tamanho do objeto. À medida que o tamanho do objeto aumenta, isso fica próximo à medida que a memória consumida pelo restante do processo se torna insignificante em comparação ao tamanho do objeto que você está tentando monitorar.
fonte
Você pode usar getSizeof () conforme mencionado abaixo para determinar o tamanho de um objeto
fonte
Uso esse truque ... Pode não ser preciso em objetos pequenos, mas acho que é muito mais preciso para um objeto complexo (como a superfície do jogo), em vez de sys.getsizeof ()
No meu windows 10, python 3.7.3, a saída é:
fonte