Efficace de la lecture de 800 GO fichier XML dans Python 2.7
Je suis de la lecture d'un 800 GO fichier xml dans python 2.7 et l'analyser avec un programme etree itératif de l'analyseur.
Actuellement, je suis juste en utilisant open('foo.txt')
sans mise en mémoire tampon de l'argument. Je suis un peu confus si c'est l'approche que je devrais prendre, ou, devrais-je utiliser un tampon d'un argument ou d'utiliser quelque chose de io comme io.BufferedReader ou io.ouvrir ou io.TextIOBase.
Un point dans la bonne direction serait très apprécié.
- 800 go de fichier texte?! Mère de Dieu...À quel moment avez-vous les gars, vous voulez dire que c'est une bonne idée de jeter dans une base de données?
- pire, le titre le dit le texte, mais le corps dit que c'est du XML
- J'espère juste pour vous que le fichier est valide XML...
- Est votre fichier de quelque chose comme:
<root><item>...</item><item>...</item>...</root>
que certains programmeurs java avant que vous avez utilisé pour vider un journal ou quelque chose? - peut-être qu'ils avaient à le faire de cette façon à respecter le mot d'ordre de la conformité auprès du département marketing.
- C'est l'un des plus drôles les commentaires que j'ai jamais lu.
- SI vous devez savoir, c'est une révision complète de vidage de Wikipedia en espagnol.
Vous devez vous connecter pour publier un commentaire.
La norme
open()
function déjà, par défaut, renvoie un tampon de fichier (si disponible sur votre plate-forme). Pour des objets de fichiers que est généralement entièrement mis en mémoire tampon.Généralement signifie ici que Python laisse cela à la C stdlib mise en œuvre; il utilise un
fopen()
appel (wfopen()
sur Windows pour prendre en charge UTF-16 noms de fichiers), ce qui signifie que le défaut de mise en mémoire tampon pour un fichier est choisi; sur Linux, je crois que ce serait de 8 ko. Pour une pure opération de lecture comme d'analyse XML de ce type de mise en mémoire tampon est exactement ce que vous voulez.L'analyse XML fait par
iterparse
lit le fichier en segments de 16384 octets (16 ko).Si vous voulez contrôler la taille de tampon, utilisez le
buffering
argument mot-clé:qui va remplacer la valeur par défaut taille de la mémoire tampon (que je devrais attendre pour correspondre à la taille de bloc du fichier ou un multiple de celui-ci). Selon cet article l'augmentation de la mémoire tampon de lecture devrait de l'aide, et d'utiliser une taille d'au moins 4 fois supérieur à celui de lire la taille de bloc de 8 octets va améliorer les performances de lecture. Dans l'exemple ci-dessus je l'ai fixé à 8 fois la ElementTree lire la taille.
La
io.open()
function représente la nouvelle Python 3 I/O de la structure des objets, où les I/O a été divisée en une nouvelle hiérarchie de types de classe pour vous donner plus de flexibilité. Le prix est plus indirection, plus de couches pour que les données de voyager à travers, et le Python de code C n'a plus de travail lui-même au lieu de laisser l'OS.Vous pourrait essayer et voir si
io.open('foo.xml', 'rb', buffering=2<<16)
va faire mieux. Ouverture enrb
mode vous donnera unio.BufferedReader
exemple.Vous ne pas souhaitez utiliser
io.TextIOWrapper
; le sous-jacent expat analyseur veut données brutes comme il va décoder le fichier XML codage lui-même. Il ne serait d'ajouter une charge supplémentaire; vous obtenez ce type si vous ouvrez dansr
(textmode) à la place.À l'aide de
io.open()
peut vous donner plus de flexibilité et une plus riche de l'API, mais la C sous-jacente de l'objet fichier est ouvert à l'aide deopen()
au lieu defopen()
, et tous de mise en mémoire tampon est géré par le Pythonio.BufferedIOBase
mise en œuvre.Votre problème sera le traitement de cette bête, pas le fichier lit, je pense. Le cache disque sera assez bien tourné de toute façon lors de la lecture d'un 800 go de fichier.
iterparse()
est pour. Il vous donne événementiel d'analyse avec le ElementTree de l'API, de sorte que vous pouvez libérer les éléments de fois que nécessaire.open()
sur un fichier sera entièrement mis en mémoire tampon; ats (votre terminal) est généralement linebuffered;b
mode binaire ne permet pas de faire une différence. Je vais suss exactement ce que "généralement" signifie demain.open()
vsio.open()
. J'aimerais utiliser la première.Avez-vous essayé un paresseux fonction?: Paresseux Méthode pour la Lecture de Gros Fichiers en Python?
cela semble déjà répondre à votre question. Cependant, je suis d'envisager d'utiliser cette méthode pour écrire vos données à une BASE de données, mysql est gratuit: http://dev.mysql.com/downloads/ , NoSQL est également gratuit et peut être un peu plus adapté aux opérations impliquant l'écriture de 800 go de données, ou des quantités similaires: http://www.oracle.com/technetwork/database/nosqldb/downloads/default-495311.html
iterparse()
déjà lit le fichier en morceaux.Je n'ai pas essayé avec une telle épopée des fichiers xml, mais la dernière fois que j'ai eu à traiter avec de grandes (et relativement simple) des fichiers xml, j'ai utilisé un analyseur sax.
Il vous donne essentiellement des rappels pour chaque "événement" et laisse à vous pour stocker les données dont vous avez besoin. Vous pouvez donner à un fichier ouvert de sorte que vous n'avez pas à le lire en une seule fois.
iterparse()
est construit au sommet d'un analyseur sax.