Comment enregistrer un dictionnaire dans un fichier?

139

J'ai un problème avec la modification d'une valeur de dict et l'enregistrement du dict dans un fichier texte (le format doit être le même), je veux seulement changer le member_phonechamp.

Mon fichier texte est au format suivant:

memberID:member_name:member_email:member_phone

et j'ai divisé le fichier texte avec:

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

Quand j'essaye de changer le member_phonestocké dans d, la valeur a changé pas flux par la clé,

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')

et comment enregistrer le dict dans un fichier texte avec le même format?

XueYuan Wang
la source

Réponses:

258

Python a le module pickle juste pour ce genre de chose.

Ces fonctions sont tout ce dont vous avez besoin pour enregistrer et charger presque tous les objets:

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)

Ces fonctions supposent que vous avez un objdossier dans votre répertoire de travail actuel, qui sera utilisé pour stocker les objets.

Notez qu'il pickle.HIGHEST_PROTOCOLs'agit d'un format binaire, qui ne peut pas toujours être pratique, mais qui est bon pour les performances. Le protocole 0est un format de texte.

Afin de sauvegarder des collections de Python, il y a le module shelve .

Zah
la source
1
save_objsemble exiger que le fichier obj/'+ name + '.pklexiste déjà. J'ai créé un dictionnaire nommé Q, save_obj(Q, "Qtable")je l'ai rempli et j'ai passé l'appel. J'ai eu une erreur: FileNotFoundError: [Errno 2] No such file or directory: 'obj/Qtable.pkl'comment créer le fichier en premier lieu avant d'y écrire?
Cure
1
@ToothpickAnemone utilise wb+pour créer un fichier, soit:with open('obj/'+ name + '.pkl', 'wb+')
andrey.s
1
@ andrey.s: Je ne pense pas que ce que vous dites fera une différence car cela ne résout pas le problème.
martineau
1
@Toothpick Anemone: L'ajout de a +au mode n'aura aucun effet sur votre problème (andrey.s est incorrect). Votre problème semble être dû à une ou deux choses. Pour que save_obj()cette réponse fonctionne, un sous-répertoire nommé "obj"doit déjà exister car open()il n'en créera pas automatiquement. Deuxièmement, le premier argument save_obj()est l'objet Python à enregistrer, pas le nom du sous-répertoire (bien que ce que vous entendiez par l' appel Qdans l'exemple ne soit pas tout à fait clair save_obj(Q, "Qtable")). Vous pouvez créer un répertoire s'il ne se termine pas déjà avec os.mkdir().
martineau
168

Pickle est probablement la meilleure option, mais au cas où quelqu'un se demanderait comment enregistrer et charger un dictionnaire dans un fichier à l'aide de 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"

Pour info: visionneuse de fichiers NPY

Franck Dernoncourt
la source
4
à quoi sert le .item ()?
Gulzar
Pourquoi cette réponse est-elle moins votée que la réponse "pickle" de @Zah? Plus complexe spatial?
Nathan
1
@frank possibilité car pickle fait partie de la bibliothèque standard de python où numpy est un projet indépendant.
Maxim Veksler
2
@Gulzar d'après ce que j'ai recherché, np.load renvoie un ndarray (faisant un le type(read_dictionary)révèle) et .item () convertit fondamentalement cet élément en un objet scalaire python qui est un dictionnaire comme indiqué ici
abhyudayasrinet
2
@Shai avez-vous installé le package numpy ...?
Eben
26

Nous pouvons également utiliser le jsonmodule dans le cas où des dictionnaires ou d'autres données peuvent être facilement mappés au format 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" ) )

Cette solution apporte de nombreux avantages , par exemple fonctionne pour Python 2.x et Python 3.x sous une forme inchangée et en plus, les données enregistrées au format JSON peuvent être facilement transférées entre de nombreuses plates-formes ou programmes différents . Ces données sont également lisibles par l'homme .

simhumileco
la source
Bonne approche, mais je ne pense pas qu'il soit sûr de l'utiliser opendirectement au lieu d'un contexte créé par with. Y a-t-il une garantie, le descripteur de fichier sera fermé en cas d' json.dumpéchec?
Dr_Zaszuś
18

Je ne sais pas quelle est votre première question, mais si vous souhaitez enregistrer un dictionnaire dans un fichier, vous devez utiliser la jsonbibliothèque. Consultez la documentation des charges et met les fonctions.

John
la source
Pourquoi json? Il est encore plus facile de simplement vider le dictionnaire Python dans un fichier en utilisant "repr"
mguijarr
5
@mguijarr mais l'analyse n'est pas aussi simple. De plus, json est facile à éditer à la main et à importer dans n'importe quel autre programme.
kalhartt
1
J'aime la suggestion de John - voir cet article pour un bon et simple exemple stackoverflow.com/a/11027021/765827
jacanterbury
9

Enregistrez et chargez le dict dans un fichier:

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
la source
3

Pour un dictionnaire de chaînes comme celui avec lequel vous avez affaire, cela pourrait être fait en utilisant uniquement les capacités de traitement de texte intégrées de Python.

(Notez que cela ne fonctionnerait pas si les valeurs sont autres.)

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
la source
Cela ne fonctionne pas sur les dictionnaires: file.write (':'. Join ([id] + values.split (':')) + '\ n') AttributeError: l'objet 'dict' n'a pas d'attribut 'split'
Shai Alon
@ShaiAlon: Pas avec tous, non. Il a certainement fait le travail avec ceux dont les valeurs sont des chaînes (qui ont une split()méthode) -qui est le sujet de cette question. Il semble que vous essayez de l'utiliser sur un dictionnaire de dictionnaires, donc non, cela ne fonctionnerait pas avec ceux-ci. Je n'apprécie pas non plus les votes négatifs des gens parce qu'ils ne comprennent pas vraiment la question (et donc le contexte des réponses fournies). Je mettrai à jour ma réponse pour faire en sorte que son utilisation soit appropriée, alors veuillez annuler votre vote défavorable.
martineau
3

Je suggérerais d'enregistrer vos données en utilisant le format JSON au lieu du format pickle, car les fichiers JSON sont lisibles par l'homme, ce qui facilite votre débogage car vos données sont petites. Les fichiers JSON sont également utilisés par d'autres programmes pour lire et écrire des données. Vous pouvez en savoir plus ici

Vous devrez installer le module JSON, vous pouvez le faire avec pip:

pip install json


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

Cela crée un fichier json avec le nom myfile.

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

Cela lit et stocke les données myfile.json dans un objet de données.

Kavin Sabharwal
la source
2

À moins que vous ne souhaitiez vraiment conserver le dictionnaire, je pense que la meilleure solution est d'utiliser le csvmodule Python pour lire le fichier. Ensuite, vous obtenez des lignes de données et vous pouvez changer member_phoneou ce que vous voulez; enfin, vous pouvez utiliser lecsv nouveau module pour enregistrer le fichier dans le même format que vous l'avez ouvert.

Code de lecture:

import csv

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

Code d'écriture:

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

Bien entendu, vous devez adapter votre change()fonction:

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
la source
qu'entend-on parOf course, you need to adapt your change() function:
kRazzy R
1
dans la question, un a dict été utilisé alors que csv fonctionne plus comme une liste
mguijarr
1

Je ne l'ai pas chronométré mais je parie que h5 est plus rapide que pickle; la taille du fichier avec compression est presque certainement plus petite.

import deepdish as dd
dd.io.save(filename, {'dict1': dict1, 'dict2': dict2}, compression=('blosc', 9))
mots pour
la source
-2

Solution rapide et sale: convertissez le dict en chaîne et enregistrez-le dans un fichier, par exemple:

#dict could be anything:

savedict = open('savedict001.txt', 'w')
savedict.write(str(dict))
savedict.close()
Patrick Stacey
la source
La conversion de dict en str et l'enregistrement ne fonctionnent pas en particulier lorsque vous avez pd.Series ou np.ndarray comme clés dans les chaînes.
Arpan Srivastava