2009-04-30 2 views
20

J'ai une liste de valeurs à virgule flottante en Python:Comment la liste de sortie des flotteurs à un fichier binaire en Python

floats = [3.14, 2.7, 0.0, -1.0, 1.1] 

Je voudrais écrire ces valeurs dans un fichier binaire en utilisant IEEE 32- codage de bits. Quelle est la meilleure façon de le faire en Python? Ma liste contient environ 200 Mo de données, donc quelque chose de "pas trop lent" serait préférable.

Puisqu'il y a 5 valeurs, je veux juste un fichier de 20 octets en sortie.

+0

Votre tableau est manquant des virgules entre les numéros. –

Répondre

30

Alex est tout à fait raison, il est plus efficace de le faire de cette façon:

from array import array 
output_file = open('file', 'wb') 
float_array = array('d', [3.14, 2.7, 0.0, -1.0, 1.1]) 
float_array.tofile(output_file) 
output_file.close() 

Et puis lire le tableau comme ça:

input_file = open('file', 'r') 
float_array = array('d') 
float_array.fromstring(input_file.read()) 

array.array objets ont également une méthode .fromfile qui peut être utilisé pour la lecture de la fi Si vous connaissez le nombre d'éléments à l'avance (par ex. à partir de la taille du fichier, ou d'un autre mécanisme)

+1

Le premier argument dans le tableau ne devrait-il pas être un «f» puisque l'encodage de 32 bits est demandé? – dmagree

+0

FWIW, il s'avère que la réponse struct est en réalité plus rapide. J'ai fait un profilage de plusieurs alternatives différentes et struct est le plus rapide d'un peu. https://gist.github.com/deanmalmgren/fd1714799dc5b5643b87#file-write_profiler-py – dino

12

Voir: Python's struct module

import struct 
s = struct.pack('f'*len(floats), *floats) 
f = open('file','wb') 
f.write(s) 
f.close() 
+0

En fait, c'est ce que je fais maintenant. Je pensais juste qu'il devait y avoir un meilleur moyen. –

+1

Et il y a un meilleur moyen - le module de tableau. Voir http://docs.python.org/library/array.html pour tous les détails. –

+0

Vous devez utiliser la syntaxe 'with'. –

10

Le module de tableau dans la bibliothèque standard peut être plus approprié pour cette tâche que le module struct que tout le monde suggère. Performance avec 200 Mo de données devrait être sensiblement mieux avec tableau.

Si vous souhaitez prendre à une variété d'options, essayez le profilage sur votre système avec something like this

8

Je ne sais pas comment NumPy comparera les performances pour votre application, mais cela peut valoir la peine d'être étudié.

En utilisant NumPy:

from numpy import array 
a = array(floats,'float32') 
output_file = open('file', 'wb') 
a.tofile(output_file) 
output_file.close() 

résultats dans un fichier de 20 octets ainsi.

+1

pas aussi rapide que l'utilisation de struct. Voir le profilage ici https://gist.github.com/deanmalmgren/fd1714799dc5b5643b87#file-write_profiler-py – dino

1

J'ai rencontré un problème similaire lors de l'écriture par inadvertance d'un fichier CSV 100+ Go. Les réponses ici ont été extrêmement utiles mais, pour aller au fond des choses, I profiled all of the solutions mentioned and then some. Toutes les exécutions de profilage ont été effectuées sur un Macbook Pro 2014 avec un SSD utilisant python 2.7. D'après ce que je vois, l'approche struct est sans aucun doute le plus rapide d'un point de vue de la performance:

6.465 seconds print_approach print list of floats 
4.621 seconds csv_approach  write csv file 
4.819 seconds csvgz_approach compress csv output using gzip 
0.374 seconds array_approach array.array.tofile 
0.238 seconds numpy_approach numpy.array.tofile 
0.178 seconds struct_approach struct.pack method