2010-12-15 65 views
6

Quel est le moyen le plus simple d'enregistrer et de charger des données en python, de préférence dans un format de sortie lisible par l'homme?Sauvegarde/chargement de données en python facile

Les données que je sauvegarde/charge sont constituées de deux vecteurs de flottants. Idéalement, ces vecteurs seraient nommés dans le fichier (par exemple X et Y).

Mes fonctions actuelles save() et load() utilisent file.readline(), file.write() et chaîne à flotteur conversion. Il doit y avoir quelque chose de mieux.

Répondre

5

Il y a plusieurs options - je ne sais pas exactement ce que vous aimez.Si les deux vecteurs ont la même longueur, vous pouvez utiliser numpy.savetxt() pour enregistrer vos vecteurs, par exemple x et y, sous forme de colonnes:

# saving: 
f = open("data", "w") 
f.write("# x y\n")  # column names 
numpy.savetxt(f, numpy.array([x, y]).T) 
# loading: 
x, y = numpy.loadtxt("data", unpack=True) 

Si vous traitez avec des grands vecteurs de flotteurs, vous devriez probablement utiliser NumPy de toute façon.

+1

il me semble que numpy.savetxt prend une chaîne comme premier argument. – nos

+0

@nos: Il prend un nom de fichier ou un objet fichier. Peut-être que les anciennes versions de NumPy n'acceptaient qu'une chaîne. Je passe un objet fichier pour pouvoir écrire la ligne d'en-tête avant. –

+0

il économise si j'utilise f = open ("data", "w +") – nos

2

Un format de sérialisation simple qui est facile pour les deux humains à lire des ordinateurs est JSON. Vous pouvez utiliser le module Python json.

18

La manière la plus simple d'obtenir une sortie lisible par un humain est d'utiliser un format de sérialisation tel qu'un JSON. Python contient une bibliothèque json que vous pouvez utiliser pour sérialiser les données vers et depuis une chaîne. Comme pickle, vous pouvez l'utiliser avec un objet IO pour l'écrire dans un fichier.

import json 

file = open('/usr/data/application/json-dump.json', 'w+') 
data = { "x": 12153535.232321, "y": 35234531.232322 } 

json.dump(data, file) 

Si vous souhaitez obtenir une chaîne simple dos au lieu de dumping à un fichier, vous pouvez utiliser JSON. décharges() à la place:

import json 
print json.dumps({ "x": 12153535.232321, "y": 35234531.232322 }) 

Relecture d'un fichier est tout aussi simple:

import json 

file = open('/usr/data/application/json-dump.json', 'r') 
print json.load(file) 

La bibliothèque JSON est complet, donc je vous recommande checking out the documentation de voir quelles sortes des choses que vous pouvez faire avec.

7
  • Si elle doit être lisible par l'homme, je aussi aller avec JSON. Sauf si vous avez besoin de l'échanger avec des gens de type entreprise , ils préfèrent XML mieux. :-)

  • Si elle doit être humaine modifiable et est pas trop complexe, je serais probablement aller avec une sorte format INI-like, comme par exemple ConfigParser.

  • Si elle est complexe, et je ne pas besoin d'être échangés contre , aller avec juste décapage des données, à moins qu'il est très complexe, auquel cas j'utiliser ZODB.

  • Si c'est beaucoup de données, et qu'il faut échanger , j'utiliserais SQL.

Cela couvre à peu près tout, je pense.

+1

Est-ce que le format CSV répond à l'une de ces exigences? – dheerosaur

+0

CSV est un bon format si vos données sont très simples (c'est-à-dire tabulaires), et vous voulez pouvoir les importer dans une feuille de calcul. Sinon, il est trop indéfini, pas facilement lisible ou modifiable, ne peut pas gérer les données complexes, et est pénible si l'ensemble de données est grand. –

0

Puisque nous parlons d'un humain éditant le fichier, je suppose que nous parlons relativement peu de données.

Que diriez-vous de l'implémentation squelette suivante. Il enregistre simplement les données sous forme de paires key=value et fonctionne avec des listes, des tuples et bien d'autres choses.

def save(fname, **kwargs): 
     f = open(fname, "wt") 
     for k, v in kwargs.items(): 
     print >>f, "%s=%s" % (k, repr(v)) 
     f.close() 

    def load(fname): 
     ret = {} 
     for line in open(fname, "rt"): 
     k, v = line.strip().split("=", 1) 
     ret[k] = eval(v) 
     return ret 

    x = [1, 2, 3] 
    y = [2.0, 1e15, -10.3] 
    save("data.txt", x=x, y=y) 
    d = load("data.txt") 
    print d["x"] 
    print d["y"] 
+0

Je n'aime pas la chose eval, il pourrait apporter des choses étranges en permettant à l'utilisateur d'exécuter du code arbitraire –

+0

En supposant que c'est simple, ast.literal_eval contourne cela. Je préfère l'approche JSON, cependant. –

0

Comme je l'ai commenté dans la réponse acceptée, en utilisant numpy cela peut être fait avec un simple-liner:

En supposant que vous avez numpy importé comme np (ce qui est pratique courante),

np.savetxt('xy.txt', np.array([x, y]).T, fmt="%.3f", header="x y") 

enregistrera les données dans le format (en option) et

x, y = np.loadtxt('xy.txt', unpack=True) 

le chargera.

Le fichier xy.txt ressemblera alors à:

# x y 
1.000 1.000 
1.500 2.250 
2.000 4.000 
2.500 6.250 
3.000 9.000 

Notez que la chaîne de format fmt=... est facultative, mais si l'objectif est lisibilité humaine, il peut se révéler très utile. Si elle est utilisée, elle est spécifiée en utilisant les codes usuels printf (Dans mon exemple: nombre à virgule flottante avec 3 décimales).