¿Cómo guardar un diccionario en un archivo?

139

Tengo problemas para cambiar un valor de dict y guardar el dict en un archivo de texto (el formato debe ser el mismo), solo quiero cambiar el member_phonecampo.

Mi archivo de texto tiene el siguiente formato:

memberID:member_name:member_email:member_phone

y dividí el archivo de texto con:

mdict={}
for line in file:
    x=line.split(':')
    a=x[0]
    b=x[1]
    c=x[2]
    d=x[3]
    e=b+':'+c+':'+d

    mdict[a]=e

Cuando trato de cambiar el member_phonealmacenado en d, el valor ha cambiado no fluye por la clave,

def change(mdict,b,c,d,e):
    a=input('ID')
    if a in mdict:
        d= str(input('phone'))
        mdict[a]=b+':'+c+':'+d
    else:
        print('not')

y cómo guardar el dict en un archivo de texto con el mismo formato?

XueYuan Wang
fuente

Respuestas:

258

Python tiene el módulo pickle solo para este tipo de cosas.

Estas funciones son todo lo que necesita para guardar y cargar casi cualquier objeto:

def save_obj(obj, name ):
    with open('obj/'+ name + '.pkl', 'wb') as f:
        pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)

def load_obj(name ):
    with open('obj/' + name + '.pkl', 'rb') as f:
        return pickle.load(f)

Estas funciones suponen que tiene una objcarpeta en su directorio de trabajo actual, que se utilizará para almacenar los objetos.

Tenga en cuenta que pickle.HIGHEST_PROTOCOLes un formato binario, que no siempre puede ser conveniente, pero es bueno para el rendimiento. El protocolo 0es un formato de texto.

Para guardar colecciones de Python existe el módulo de estantería .

Zah
fuente
1
save_objparece requerir que el archivo obj/'+ name + '.pklya exista. Creé un diccionario llamado Q, lo poblé e hice la llamada save_obj(Q, "Qtable")Recibí un error: FileNotFoundError: [Errno 2] No such file or directory: 'obj/Qtable.pkl'¿Cómo se crea el archivo en primer lugar antes de escribir en él?
Palillo de dientes Anemone
1
@ToothpickAnemone uso wb+para crear el archivo, es decir:with open('obj/'+ name + '.pkl', 'wb+')
andrey.s
1
@ andrey.s: No creo que lo que diga haga alguna diferencia porque no resuelve el problema.
Martineau
1
@Toothpick Anemone: agregar +a al modo no tendrá ningún efecto en su problema (andrey.s es incorrecto). Su problema parece que se debe a una o dos cosas. Para save_obj()que funcione en esta respuesta, ya"obj" debe existir un subdirectorio llamado porque open()no creará uno automáticamente. En segundo lugar, el primer argumento save_obj()es el objeto Python que se va a guardar, no el nombre del subdirectorio (aunque no está del todo claro qué quería decir con Qen la save_obj(Q, "Qtable")llamada de ejemplo ). Puede crear un directorio si aún no existe os.mkdir().
Martineau
168

Pickle es probablemente la mejor opción, pero en caso de que alguien se pregunte cómo guardar y cargar un diccionario en un archivo usando NumPy:

import numpy as np

# Save
dictionary = {'hello':'world'}
np.save('my_file.npy', dictionary) 

# Load
read_dictionary = np.load('my_file.npy',allow_pickle='TRUE').item()
print(read_dictionary['hello']) # displays "world"

FYI: visor de archivos NPY

Franck Dernoncourt
fuente
44
¿Para qué sirve el .item ()?
Gulzar
¿Por qué esta respuesta es menos votada que la respuesta "pickle" de @Zah? ¿Más complejo espacial?
Nathan
1
posibilidad de @frank porque pickle es parte de la biblioteca estándar de python donde numpy es un proyecto independiente
Maxim Veksler
2
@Gulzar de lo que busqué, np.load devuelve un ndarray (haciendo una type(read_dictionary)revelación) y .item () básicamente convierte ese elemento en un objeto escalar python que es un diccionario como se indica aquí
abhyudayasrinet
2
@Shai, ¿has instalado el paquete numpy ...?
Eben
26

También podemos usar el jsonmódulo en el caso de que los diccionarios u otros datos se puedan asignar fácilmente al formato JSON .

import json

# Serialize data into file:
json.dump( data, open( "file_name.json", 'w' ) )

# Read data from file:
data = json.load( open( "file_name.json" ) )

Esta solución aporta muchos beneficios , por ejemplo, las obras de Python 2.x y 3.x Python en forma inalterada y, además, los datos guardados en JSON formato puede ser transferido fácilmente entre muchas plataformas o programas diferentes . Estos datos también son legibles por humanos .

simhumileco
fuente
Buen enfoque, pero no creo que sea seguro usarlo opendirectamente en lugar de un contexto creado por with. ¿Hay una garantía, el identificador de archivo se cerrará si json.dumpfalla?
Dr_Zaszuś
18

No estoy seguro de cuál es su primera pregunta, pero si desea guardar un diccionario en un archivo, debe usar la jsonbiblioteca. Busque la documentación de las cargas y pone funciones.

Juan
fuente
Porque json Es incluso más fácil volcar el diccionario Python en un archivo usando "repr"
mguijarr
55
@mguijarr, pero analizarlo de nuevo no es tan fácil. Además, json es fácil de editar a mano e importar a cualquier otro programa.
kalhartt
1
Me gusta la sugerencia de John: vea esta publicación para ver un ejemplo bueno y simple stackoverflow.com/a/11027021/765827
jacanterbury
9

Guardar y cargar dict al archivo:

def save_dict_to_file(dic):
    f = open('dict.txt','w')
    f.write(str(dic))
    f.close()

def load_dict_from_file():
    f = open('dict.txt','r')
    data=f.read()
    f.close()
    return eval(data)
Junglejet
fuente
3

Para un diccionario de cadenas como el que está tratando, podría hacerse utilizando solo las capacidades de procesamiento de texto incorporadas de Python.

(Tenga en cuenta que esto no funcionaría si los valores son otra cosa).

with open('members.txt') as file:
    mdict={}
    for line in file:
        a, b, c, d = line.strip().split(':')
        mdict[a] = b + ':' + c + ':' + d

a = input('ID: ')
if a not in mdict:
    print('ID {} not found'.format(a))
else:
    b, c, d = mdict[a].split(':')
    d = input('phone: ')
    mdict[a] = b + ':' + c + ':' + d  # update entry
    with open('members.txt', 'w') as file:  # rewrite file
        for id, values in mdict.items():
            file.write(':'.join([id] + values.split(':')) + '\n')
Martineau
fuente
Esto no funciona en los diccionarios: file.write (':'. Join ([id] + values.split (':')) + '\ n') AttributeError: el objeto 'dict' no tiene atributo 'split'
Shai Alon
@ShaiAlon: No con todos ellos, no. Definitivamente hace el trabajo con aquellos cuyos valores son cadenas (que tienen un split()método) -que es el tema de esta pregunta. Parece que estás tratando de usarlo en un diccionario de diccionarios, así que no, no funcionaría con ellos. Tampoco aprecio los votos negativos de la gente porque realmente no entienden la pregunta (y, por lo tanto, el contexto de las respuestas proporcionadas). Actualizaré mi respuesta cuando sea apropiado usarla, así que deshaga su voto negativo.
Martineau
3

Sugeriría guardar sus datos usando el formato JSON en lugar del formato pickle ya que los archivos JSON son legibles por humanos, lo que facilita su depuración ya que sus datos son pequeños. Los archivos JSON también son utilizados por otros programas para leer y escribir datos. Puedes leer más sobre esto aquí

Deberá instalar el módulo JSON, puede hacerlo con pip:

pip install json


# To save the dictionary into a file:
json.dump( data, open( "myfile.json", 'w' ) )

Esto crea un archivo json con el nombre myfile.

# To read data from file:
data = json.load( open( "myfile.json" ) )

Esto lee y almacena los datos myfile.json en un objeto de datos.

Kavin Sabharwal
fuente
2

A menos que realmente desee conservar el diccionario, creo que la mejor solución es utilizar el csvmódulo Python para leer el archivo. Luego, obtienes filas de datos y puedes cambiar member_phoneo lo que quieras; finalmente, puede usar el csvmódulo nuevamente para guardar el archivo en el mismo formato en que lo abrió.

Código para leer:

import csv

with open("my_input_file.txt", "r") as f:
   reader = csv.reader(f, delimiter=":")
   lines = list(reader)

Código para escribir:

with open("my_output_file.txt", "w") as f:
   writer = csv.writer(f, delimiter=":")
   writer.writerows(lines)

Por supuesto, debe adaptar su change()función:

def change(lines):
    a = input('ID')
    for line in lines:
      if line[0] == a:
        d=str(input("phone"))
        line[3]=d
        break
    else:
      print "not"
mguijarr
fuente
qué se entiende porOf course, you need to adapt your change() function:
kRazzy R
1
en la pregunta, dict se utilizó a mientras que csv funciona más como una lista
mguijarr
1

No lo he cronometrado, pero apuesto a que h5 es más rápido que el encurtido; el tamaño del archivo con compresión es casi seguro más pequeño.

import deepdish as dd
dd.io.save(filename, {'dict1': dict1, 'dict2': dict2}, compression=('blosc', 9))
palabras por el contrario
fuente
-2

Solución rápida y sucia: convierta el dict a cadena y guárdelo en un archivo, por ejemplo:

#dict could be anything:

savedict = open('savedict001.txt', 'w')
savedict.write(str(dict))
savedict.close()
Patrick Stacey
fuente
Convertir dict a str y guardar no funciona especialmente cuando tienes pd.Series o np.ndarray como tus claves en las cadenas.
Arpan Srivastava