Python orientado a objetos - serialização de objetos
No contexto de armazenamento de dados, serialização é o processo de tradução de estruturas de dados ou estado do objeto em um formato que pode ser armazenado (por exemplo, em um arquivo ou buffer de memória) ou transmitido e reconstruído posteriormente.
Na serialização, um objeto é transformado em um formato que pode ser armazenado, de forma a ser capaz de desserializá-lo posteriormente e recriar o objeto original a partir do formato serializado.
Salmoura
Pickling é o processo pelo qual uma hierarquia de objetos Python é convertida em um fluxo de bytes (geralmente não legível por humanos) para ser gravado em um arquivo, isso também é conhecido como serialização. Unpickling é a operação reversa, por meio da qual um fluxo de bytes é convertido de volta em uma hierarquia de objetos Python funcional.
Pickle é a maneira operacionalmente mais simples de armazenar o objeto. O módulo Python Pickle é uma maneira orientada a objetos de armazenar objetos diretamente em um formato de armazenamento especial.
O que é que isso pode fazer?
- Pickle pode armazenar e reproduzir dicionários e listas com muita facilidade.
- Armazena atributos de objeto e os restaura de volta ao mesmo estado.
O que picles não pode fazer?
- Ele não salva um código de objeto. Apenas seus valores de atributos.
- Ele não pode armazenar identificadores de arquivo ou soquetes de conexão.
Resumindo, podemos dizer que a decapagem é uma maneira de armazenar e recuperar variáveis de dados para dentro e para fora de arquivos onde as variáveis podem ser listas, classes, etc.
Para conservar algo você deve -
- importar picles
- Escreva uma variável para o arquivo, algo como
pickle.dump(mystring, outfile, protocol),
onde o protocolo do terceiro argumento é opcional. Para remover algo, você deve -
Picles de importação
Escreva uma variável em um arquivo, algo como
myString = pickle.load(inputfile)
Métodos
A interface pickle oferece quatro métodos diferentes.
dump() - O método dump () serializa para um arquivo aberto (objeto semelhante a arquivo).
dumps() - Serializa em uma string
load() - Desserializa a partir de um objeto aberto.
loads() - Desserializa de uma string.
Com base no procedimento acima, abaixo está um exemplo de “decapagem”.
Resultado
My Cat pussy is White and has 4 legs
Would you like to see her pickled? Here she is!
b'\x80\x03c__main__\nCat\nq\x00)\x81q\x01}q\x02(X\x0e\x00\x00\x00number_of_legsq\x03K\x04X\x05\x00\x00\x00colorq\x04X\x05\x00\x00\x00Whiteq\x05ub.'
Portanto, no exemplo acima, criamos uma instância de uma classe Cat e a separamos, transformando nossa instância “Cat” em um array simples de bytes.
Dessa forma, podemos armazenar facilmente a matriz de bytes em um arquivo binário ou em um campo de banco de dados e restaurá-la de volta à sua forma original a partir de nosso suporte de armazenamento posteriormente.
Além disso, se você quiser criar um arquivo com um objeto conservado, pode usar o método dump () (em vez dos dumps * () * um), passando também um arquivo binário aberto e o resultado da conservação será armazenado no arquivo automaticamente.
[….]
binary_file = open(my_pickled_Pussy.bin', mode='wb')
my_pickled_Pussy = pickle.dump(Pussy, binary_file)
binary_file.close()
Retirada
O processo que pega uma matriz binária e a converte em uma hierarquia de objetos é chamado de remoção da separação.
O processo de remoção é feito usando a função load () do módulo pickle e retorna uma hierarquia completa de objetos a partir de um array de bytes simples.
Vamos usar a função load em nosso exemplo anterior.
Resultado
MeOw is black
Pussy is white
JSON
JSON (JavaScript Object Notation) faz parte da biblioteca padrão do Python e é um formato de intercâmbio de dados leve. É fácil para humanos ler e escrever. É fácil de analisar e gerar.
Devido à sua simplicidade, JSON é uma maneira pela qual armazenamos e trocamos dados, o que é realizado por meio de sua sintaxe JSON, e é usado em muitos aplicativos da web. Por se encontrar em formato legível por humanos, este pode ser um dos motivos para utilizá-lo na transmissão de dados, além de sua eficácia no trabalho com APIs.
Um exemplo de dados formatados em JSON é o seguinte -
{"EmployID": 40203, "Name": "Zack", "Age":54, "isEmployed": True}
Python simplifica o trabalho com arquivos Json. O módulo sused para este propósito é o módulo JSON. Este módulo deve ser incluído (embutido) na instalação do Python.
Então, vamos ver como podemos converter o dicionário Python em JSON e gravá-lo em um arquivo de texto.
JSON para Python
Ler JSON significa converter JSON em um valor Python (objeto). A biblioteca json analisa JSON em um dicionário ou lista em Python. Para fazer isso, usamos a função load () (carregar de uma string), como segue -
Resultado
Abaixo está um exemplo de arquivo json,
data1.json
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
O conteúdo acima (Data1.json) parece um dicionário convencional. Podemos usar pickle para armazenar este arquivo, mas a saída dele não é de forma legível por humanos.
JSON (Java Script Object Notification) é um formato muito simples e esse é um dos motivos de sua popularidade. Agora vamos dar uma olhada na saída json por meio do programa abaixo.
Resultado
Acima, abrimos o arquivo json (data1.json) para leitura, obtemos o manipulador de arquivo e passamos para json.load e recuperamos o objeto. Quando tentamos imprimir a saída do objeto, é o mesmo que o arquivo json. Embora o tipo do objeto seja um dicionário, ele surge como um objeto Python. Escrever para o json é simples, pois vimos este pickle. Acima, carregamos o arquivo json, adicionamos outro par de valores-chave e gravamos de volta no mesmo arquivo json. Agora, se virmos data1.json, ele parece diferente, ou seja, não no mesmo formato que vemos anteriormente.
Para fazer com que nossa saída pareça a mesma (formato legível por humanos), adicione alguns argumentos em nossa última linha do programa,
json.dump(conf, fh, indent = 4, separators = (‘,’, ‘: ‘))
Da mesma forma que o pickle, podemos imprimir a string com despejos e carregar com cargas. Abaixo está um exemplo disso,
YAML
YAML pode ser o padrão de serialização de dados mais amigável para todas as linguagens de programação.
O módulo Python yaml é chamado pyaml
YAML é uma alternativa para JSON -
Human readable code - YAML é o formato mais legível por humanos, tanto que até mesmo seu conteúdo de primeira página é exibido em YAML para mostrar isso.
Compact code - Em YAML, usamos recuo de espaço em branco para denotar a estrutura, não os colchetes.
Syntax for relational data - Para referências internas, usamos âncoras (&) e aliases (*).
One of the area where it is used widely is for viewing/editing of data structures - por exemplo, arquivos de configuração, despejando durante a depuração e cabeçalhos de documentos.
Instalando YAML
Como yaml não é um módulo embutido, precisamos instalá-lo manualmente. A melhor maneira de instalar o yaml em uma máquina Windows é através do pip. Execute o comando abaixo no seu terminal Windows para instalar o yaml,
pip install pyaml (Windows machine)
sudo pip install pyaml (*nix and Mac)
Ao executar o comando acima, a tela exibirá algo como abaixo com base na versão atual mais recente.
Collecting pyaml
Using cached pyaml-17.12.1-py2.py3-none-any.whl
Collecting PyYAML (from pyaml)
Using cached PyYAML-3.12.tar.gz
Installing collected packages: PyYAML, pyaml
Running setup.py install for PyYAML ... done
Successfully installed PyYAML-3.12 pyaml-17.12.1
Para testá-lo, vá para o shell Python e importe o módulo yaml, importe yaml, se nenhum erro for encontrado, então podemos dizer que a instalação foi bem-sucedida.
Depois de instalar o pyaml, vamos dar uma olhada no código abaixo,
script_yaml1.py
Acima, criamos três estruturas de dados diferentes, dicionário, lista e tupla. Em cada estrutura, fazemos yaml.dump. O ponto importante é como a saída é exibida na tela.
Resultado
A saída do dicionário parece limpa, por exemplo. valor chave.
Espaço em branco para separar objetos diferentes.
A lista é marcada com traço (-)
A tupla é indicada primeiro com !! Python / tupla e, em seguida, no mesmo formato das listas.
Carregando um arquivo yaml
Digamos que eu tenha um arquivo yaml, que contém,
---
# An employee record
name: Raagvendra Joshi
job: Developer
skill: Oracle
employed: True
foods:
- Apple
- Orange
- Strawberry
- Mango
languages:
Oracle: Elite
power_builder: Elite
Full Stack Developer: Lame
education:
4 GCSEs
3 A-Levels
MCA in something called com
Agora vamos escrever um código para carregar esse arquivo yaml por meio da função yaml.load. Abaixo está o código para o mesmo.
Como a saída não parece muito legível, eu a embelezo usando json no final. Compare a saída que obtivemos e o arquivo yaml real que temos.
Resultado
Um dos aspectos mais importantes do desenvolvimento de software é a depuração. Nesta seção, veremos diferentes maneiras de depurar Python com o depurador embutido ou depuradores de terceiros.
PDB - o depurador Python
O módulo PDB suporta a definição de pontos de interrupção. Um ponto de interrupção é uma pausa intencional do programa, onde você pode obter mais informações sobre o estado do programa.
Para definir um ponto de interrupção, insira a linha
pdb.set_trace()
Exemplo
pdb_example1.py
import pdb
x = 9
y = 7
pdb.set_trace()
total = x + y
pdb.set_trace()
Inserimos alguns pontos de interrupção neste programa. O programa fará uma pausa em cada ponto de interrupção (pdb.set_trace ()). Para visualizar o conteúdo de uma variável, basta digitar o nome da variável.
c:\Python\Python361>Python pdb_example1.py
> c:\Python\Python361\pdb_example1.py(8)<module>()
-> total = x + y
(Pdb) x
9
(Pdb) y
7
(Pdb) total
*** NameError: name 'total' is not defined
(Pdb)
Pressione c ou continue com a execução dos programas até o próximo ponto de interrupção.
(Pdb) c
--Return--
> c:\Python\Python361\pdb_example1.py(8)<module>()->None
-> total = x + y
(Pdb) total
16
Eventualmente, você precisará depurar programas muito maiores - programas que usam sub-rotinas. E, às vezes, o problema que você está tentando encontrar está dentro de uma sub-rotina. Considere o seguinte programa.
import pdb
def squar(x, y):
out_squared = x^2 + y^2
return out_squared
if __name__ == "__main__":
#pdb.set_trace()
print (squar(4, 5))
Agora, ao executar o programa acima,
c:\Python\Python361>Python pdb_example2.py
> c:\Python\Python361\pdb_example2.py(10)<module>()
-> print (squar(4, 5))
(Pdb)
Podemos usar ?para obter ajuda, mas a seta indica a linha que está prestes a ser executada. Neste ponto, é útil acertar s paras para entrar nessa linha.
(Pdb) s
--Call--
>c:\Python\Python361\pdb_example2.py(3)squar()
-> def squar(x, y):
Esta é uma chamada para uma função. Se você quiser uma visão geral de onde você está em seu código, tente l -
(Pdb) l
1 import pdb
2
3 def squar(x, y):
4 -> out_squared = x^2 + y^2
5
6 return out_squared
7
8 if __name__ == "__main__":
9 pdb.set_trace()
10 print (squar(4, 5))
[EOF]
(Pdb)
Você pode pressionar n para avançar para a próxima linha. Neste ponto, você está dentro do método out_squared e tem acesso à variável declarada dentro da função .ie x e y.
(Pdb) x
4
(Pdb) y
5
(Pdb) x^2
6
(Pdb) y^2
7
(Pdb) x**2
16
(Pdb) y**2
25
(Pdb)
Portanto, podemos ver que o operador ^ não é o que queríamos, em vez disso, precisamos usar o operador ** para fazer os quadrados.
Desta forma, podemos depurar nosso programa dentro das funções / métodos.
Exploração madeireira
O módulo de registro faz parte da Biblioteca Padrão do Python desde a versão 2.3 do Python. Como é um módulo embutido, todos os módulos Python podem participar do registro, para que o log do nosso aplicativo possa incluir sua própria mensagem integrada com mensagens de módulo de terceiros. Ele oferece muita flexibilidade e funcionalidade.
Benefícios do registro
Diagnostic logging - Registra eventos relacionados ao funcionamento do aplicativo.
Audit logging - Registra eventos para análise de negócios.
As mensagens são gravadas e registradas em níveis de “gravidade” e mínimo
DEBUG (debug()) - mensagens de diagnóstico para desenvolvimento.
INFO (info()) - mensagens padrão de “progresso”.
WARNING (warning()) - detectou um problema não sério.
ERROR (error()) - encontrou um erro, possivelmente sério.
CRITICAL (critical()) - geralmente um erro fatal (o programa pára).
Vamos dar uma olhada no programa simples abaixo,
import logging
logging.basicConfig(level=logging.INFO)
logging.debug('this message will be ignored') # This will not print
logging.info('This should be logged') # it'll print
logging.warning('And this, too') # It'll print
Acima, estamos registrando mensagens no nível de gravidade. Primeiro importamos o módulo, chamamos basicConfig e definimos o nível de registro. O nível que definimos acima é INFO. Então, temos três instruções diferentes: instrução de depuração, instrução de informação e uma instrução de aviso.
Saída de logging1.py
INFO:root:This should be logged
WARNING:root:And this, too
Como a instrução info está abaixo da instrução debug, não podemos ver a mensagem de depuração. Para obter a instrução de depuração também no terminal de saída, tudo o que precisamos mudar é o nível basicConfig.
logging.basicConfig(level = logging.DEBUG)
E na saída podemos ver,
DEBUG:root:this message will be ignored
INFO:root:This should be logged
WARNING:root:And this, too
Além disso, o comportamento padrão significa que se não definirmos nenhum nível de registro, é aviso. Basta comentar a segunda linha do programa acima e executar o código.
#logging.basicConfig(level = logging.DEBUG)
Resultado
WARNING:root:And this, too
O nível de registro integrado do Python são, na verdade, inteiros.
>>> import logging
>>>
>>> logging.DEBUG
10
>>> logging.CRITICAL
50
>>> logging.WARNING
30
>>> logging.INFO
20
>>> logging.ERROR
40
>>>
Também podemos salvar as mensagens de log no arquivo.
logging.basicConfig(level = logging.DEBUG, filename = 'logging.log')
Agora, todas as mensagens de log irão para o arquivo (logging.log) em seu diretório de trabalho atual ao invés da tela. Esta é uma abordagem muito melhor, pois nos permite fazer uma pós-análise das mensagens que recebemos.
Também podemos definir o carimbo de data com nossa mensagem de log.
logging.basicConfig(level=logging.DEBUG, format = '%(asctime)s %(levelname)s:%(message)s')
A saída terá algo como,
2018-03-08 19:30:00,066 DEBUG:this message will be ignored
2018-03-08 19:30:00,176 INFO:This should be logged
2018-03-08 19:30:00,201 WARNING:And this, too
avaliação comparativa
Benchmarking ou criação de perfil são basicamente para testar a rapidez com que seu código é executado e onde estão os gargalos. O principal motivo para fazer isso é a otimização.
timeit
Python vem com um módulo embutido chamado timeit. Você pode usá-lo para cronometrar pequenos trechos de código. O módulo timeit usa funções de tempo específicas da plataforma para que você obtenha os tempos mais precisos possíveis.
Assim, permite-nos comparar duas remessas de código tomadas por cada uma e, em seguida, otimizar os scripts para obter um melhor desempenho.
O módulo timeit possui uma interface de linha de comando, mas também pode ser importado.
Existem duas maneiras de chamar um script. Vamos usar o script primeiro, para isso execute o código abaixo e veja a saída.
import timeit
print ( 'by index: ', timeit.timeit(stmt = "mydict['c']", setup = "mydict = {'a':5, 'b':10, 'c':15}", number = 1000000))
print ( 'by get: ', timeit.timeit(stmt = 'mydict.get("c")', setup = 'mydict = {"a":5, "b":10, "c":15}', number = 1000000))
Resultado
by index: 0.1809192126703489
by get: 0.6088525265034692
Acima, usamos dois métodos diferentes, ou seja, por subscrito e conseguimos acessar o valor da chave do dicionário. Executamos a instrução 1 milhão de vezes, pois é muito rápida para dados muito pequenos. Agora podemos ver o acesso ao índice muito mais rápido em comparação com o get. Podemos executar o código multiplicar vezes e haverá uma pequena variação no tempo de execução para obter um melhor entendimento.
Outra forma é executar o teste acima na linha de comando. Vamos fazer isso,
c:\Python\Python361>Python -m timeit -n 1000000 -s "mydict = {'a': 5, 'b':10, 'c':15}" "mydict['c']"
1000000 loops, best of 3: 0.187 usec per loop
c:\Python\Python361>Python -m timeit -n 1000000 -s "mydict = {'a': 5, 'b':10, 'c':15}" "mydict.get('c')"
1000000 loops, best of 3: 0.659 usec per loop
A saída acima pode variar com base no hardware do seu sistema e em todos os aplicativos que estão executando atualmente no seu sistema.
Abaixo, podemos usar o módulo timeit, se quisermos chamar uma função. Como podemos adicionar várias instruções dentro da função para testar.
import timeit
def testme(this_dict, key):
return this_dict[key]
print (timeit.timeit("testme(mydict, key)", setup = "from __main__ import testme; mydict = {'a':9, 'b':18, 'c':27}; key = 'c'", number = 1000000))
Resultado
0.7713474590139164