Armazenando dicionários Python


198

Estou acostumado a trazer dados para dentro e para fora do Python usando arquivos .csv, mas há desafios óbvios nisso. Algum conselho sobre maneiras simples de armazenar um dicionário (ou conjuntos de dicionários) em um arquivo json ou pck? Por exemplo:

data = {}
data ['key1'] = "keyinfo"
data ['key2'] = "keyinfo2"

Gostaria de saber como salvar isso e como carregá-lo novamente.


8
Você leu a documentação dos módulos padrão json ou pickle ?
Greg Hewgill 17/08/11

Respostas:


443

Economia de picles :

try:
    import cPickle as pickle
except ImportError:  # python 3.x
    import pickle

with open('data.p', 'wb') as fp:
    pickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)

Consulte a documentação do módulo pickle para obter informações adicionais sobre o protocolargumento.

Carga em conserva :

with open('data.p', 'rb') as fp:
    data = pickle.load(fp)

Salvar JSON :

import json

with open('data.json', 'w') as fp:
    json.dump(data, fp)

Forneça argumentos extras como sort_keysou indentpara obter um resultado bonito. O argumento sort_keys classificará as chaves em ordem alfabética e o indent recuará sua estrutura de dados com indent=Nespaços.

json.dump(data, fp, sort_keys=True, indent=4)

Carregamento JSON :

with open('data.json', 'r') as fp:
    data = json.load(fp)

4
O JSON faz dicionários de forma nativa (embora eles obviamente não se comportem exatamente como um dicionário python enquanto está na memória, para fins de persistência, eles são idênticos). De fato, a unidade fundamental em json é o "Objeto", definido como {<string>: <value>}. Parece familiar? O módulo json na biblioteca padrão suporta todos os tipos nativos do Python e pode ser facilmente estendido com um conhecimento mínimo de json para suportar classes definidas pelo usuário. A página inicial do JSON define completamente o idioma em pouco mais de 3 páginas impressas, facilitando a absorção / digestão rapidamente.
Jonathanb

1
Vale a pena conhecer também o terceiro argumento pickle.dump. Se o arquivo não precisar ser legível por humanos, poderá acelerar bastante as coisas.
Steve Jessop

11
Se você adicionar sort_keys e argumentos de recuo à chamada de despejo, obterá um resultado muito mais bonito. por exemplo: json.dump(data, fp, sort_keys=True, indent=4). Mais informações podem ser encontradas aqui
juliusmh

1
Provavelmente você deve usarpickle.dump(data, fp, protocol=pickle.HIGHEST_PROTOCOL)
Martin Thoma

1
Para python 3, useimport pickle
danger89

35

Exemplo mínimo, gravando diretamente em um arquivo:

import json
json.dump(data, open(filename, 'wb'))
data = json.load(open(filename))

ou abrir / fechar com segurança:

import json
with open(filename, 'wb') as outfile:
    json.dump(data, outfile)
with open(filename) as infile:
    data = json.load(infile)

Se você deseja salvá-lo em uma string em vez de em um arquivo:

import json
json_str = json.dumps(data)
data = json.loads(json_str)


5

Para gravar em um arquivo:

import json
myfile.write(json.dumps(mydict))

Para ler de um arquivo:

import json
mydict = json.loads(myfile.read())

myfile é o objeto de arquivo no qual você armazenou o dict.


você sabe que o json tem que pegar arquivos como argumentos e gravar diretamente neles?

json.dump(myfile)ejson.load(myfile)
Niklas R

5

Se você estiver após a serialização, mas não precisará dos dados em outros programas, recomendo fortemente o shelvemódulo. Pense nisso como um dicionário persistente.

myData = shelve.open('/path/to/file')

# check for values.
keyVar in myData

# set values
myData[anotherKey] = someValue

# save the data for future use.
myData.close()

2
Se você deseja armazenar um ditado inteiro ou carregar um ditado inteiro, jsoné mais conveniente. shelveé melhor apenas para acessar uma chave de cada vez.
precisa saber é

3

Se você quiser uma alternativa para pickleou json, poderá usar klepto.

>>> init = {'y': 2, 'x': 1, 'z': 3}
>>> import klepto
>>> cache = klepto.archives.file_archive('memo', init, serialized=False)
>>> cache        
{'y': 2, 'x': 1, 'z': 3}
>>>
>>> # dump dictionary to the file 'memo.py'
>>> cache.dump() 
>>> 
>>> # import from 'memo.py'
>>> from memo import memo
>>> print memo
{'y': 2, 'x': 1, 'z': 3}

Com klepto, se você tivesse usado serialized=True, o dicionário teria sido gravado memo.pklcomo um dicionário em conserva em vez de com texto não criptografado.

Você pode obter kleptoaqui: https://github.com/uqfoundation/klepto

dillé provavelmente uma escolha melhor para a decapagem do que para picklesi mesma, pois dillpode serializar quase tudo em python. kleptotambém pode usar dill.

Você pode obter dillaqui: https://github.com/uqfoundation/dill

O mumbo-jumbo adicional nas primeiras linhas é porque kleptopode ser configurado para armazenar dicionários em um arquivo, em um contexto de diretório ou em um banco de dados SQL. A API é a mesma para o que você escolher como arquivo morto. Ele fornece um dicionário "arquivável" com o qual você pode usar loade dumpinteragir com o arquivo.


3

Este é um tópico antigo, mas, para ser completo, devemos incluir o ConfigParser e o configparser, que fazem parte da biblioteca padrão em Python 2 e 3, respectivamente. Este módulo lê e grava em um arquivo config / ini e (pelo menos no Python 3) se comporta de várias maneiras, como um dicionário. Ele tem o benefício adicional de poder armazenar vários dicionários em seções separadas do seu arquivo config / ini e recuperá-los. Doce!

Exemplo do Python 2.7.x.

import ConfigParser

config = ConfigParser.ConfigParser()

dict1 = {'key1':'keyinfo', 'key2':'keyinfo2'}
dict2 = {'k1':'hot', 'k2':'cross', 'k3':'buns'}
dict3 = {'x':1, 'y':2, 'z':3}

# make each dictionary a separate section in config
config.add_section('dict1')
for key in dict1.keys():
    config.set('dict1', key, dict1[key])

config.add_section('dict2')
for key in dict2.keys():
    config.set('dict2', key, dict2[key])

config.add_section('dict3')
for key in dict3.keys():
    config.set('dict3', key, dict3[key])

# save config to file
f = open('config.ini', 'w')
config.write(f)
f.close()

# read config from file
config2 = ConfigParser.ConfigParser()
config2.read('config.ini')

dictA = {}
for item in config2.items('dict1'):
    dictA[item[0]] = item[1]

dictB = {}
for item in config2.items('dict2'):
    dictB[item[0]] = item[1]

dictC = {}
for item in config2.items('dict3'):
    dictC[item[0]] = item[1]

print(dictA)
print(dictB)
print(dictC)

Exemplo de Python 3.X.

import configparser

config = configparser.ConfigParser()

dict1 = {'key1':'keyinfo', 'key2':'keyinfo2'}
dict2 = {'k1':'hot', 'k2':'cross', 'k3':'buns'}
dict3 = {'x':1, 'y':2, 'z':3}

# make each dictionary a separate section in config
config['dict1'] = dict1
config['dict2'] = dict2
config['dict3'] = dict3

# save config to file
f = open('config.ini', 'w')
config.write(f)
f.close()

# read config from file
config2 = configparser.ConfigParser()
config2.read('config.ini')

# ConfigParser objects are a lot like dictionaries, but if you really
# want a dictionary you can ask it to convert a section to a dictionary
dictA = dict(config2['dict1'] )
dictB = dict(config2['dict2'] )
dictC = dict(config2['dict3'])

print(dictA)
print(dictB)
print(dictC)

saída do console

{'key2': 'keyinfo2', 'key1': 'keyinfo'}
{'k1': 'hot', 'k2': 'cross', 'k3': 'buns'}
{'z': '3', 'y': '2', 'x': '1'}

conteúdo do config.ini

[dict1]
key2 = keyinfo2
key1 = keyinfo

[dict2]
k1 = hot
k2 = cross
k3 = buns

[dict3]
z = 3
y = 2
x = 1

1

Se salvar em um arquivo json, a melhor e mais fácil maneira de fazer isso é:

import json
with open("file.json", "wb") as f:
    f.write(json.dumps(dict).encode("utf-8"))

por que isso é mais fácil do json.dump( )que o descrito na outra resposta?
baxx 20/04

0

meu caso de uso foi salvar vários objetos json em um arquivo e a resposta de marty me ajudou um pouco. Mas, para servir ao meu caso de uso, a resposta não estava completa, pois substituiria os dados antigos toda vez que uma nova entrada é salva.

Para salvar várias entradas em um arquivo, é necessário verificar o conteúdo antigo (isto é, ler antes de escrever). Um arquivo típico que contém dados json terá a listou a objectcomo root. Por isso, considerei que meu arquivo json sempre tem uma list of objectse toda vez que adiciono dados a ele, basta carregar a lista primeiro, anexar meus novos dados e despejá-lo novamente em uma instância gravável de file ( w):

def saveJson(url,sc): #this function writes the 2 values to file
    newdata = {'url':url,'sc':sc}
    json_path = "db/file.json"

    old_list= []
    with open(json_path) as myfile:  #read the contents first
        old_list = json.load(myfile)
    old_list.append(newdata)

    with open(json_path,"w") as myfile:  #overwrite the whole content
        json.dump(old_list,myfile,sort_keys=True,indent=4)

    return "sucess"

o novo arquivo json será mais ou menos assim:

[
    {
        "sc": "a11",
        "url": "www.google.com"
    },
    {
        "sc": "a12",
        "url": "www.google.com"
    },
    {
        "sc": "a13",
        "url": "www.google.com"
    }
]

NOTA: É essencial ter um arquivo nomeado file.jsoncom []dados iniciais para que essa abordagem funcione

PS: não relacionado à pergunta original, mas essa abordagem também pode ser aprimorada ainda mais, verificando se a entrada já existe (com base em 1 / várias chaves) e somente depois anexando e salvando os dados. Deixe-me saber se alguém precisar dessa verificação, acrescentarei à resposta

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.