So sparen Sie Speicher, wenn Sie in Python großes XML mit mehreren GB oder mehr lesen

Einführung

Es ist lange her, dass JSON beim Austausch maschinenlesbarer Daten zum Mainstream geworden ist, aber Daten werden manchmal in XML verteilt (z. B. Daten, die von einer alten Institution veröffentlicht wurden). Wenn Sie beispielsweise eine Verarbeitung in natürlicher Sprache durchführen, verfügt der Syntaxanalysator "CaboCha" über eine Option ("-f 3"), mit der das Analyseergebnis im XML-Format ausgegeben werden kann, sodass die Ergebnisverarbeitung im sogenannten "Gitter" -Format erfolgt. Ich denke, es kann in dem Sinne verwendet werden, dass es einfacher sein wird.

Im letzteren Fall habe ich versucht, das Ergebnis der Syntaxanalyse eines großen Korpus in XML zu speichern. Als ich jedoch versuchte, 8 GB XML auf dem Computer mit 64 GB Arbeitsspeicher zu verarbeiten, war der Arbeitsspeicher voll. Ich blieb in der Mitte stecken (ich spucke nicht einmal einen Fehler aus). Ich war ein wenig überrascht, weil ich es auf 64 GB gebracht habe, um mein Bestes zu geben, um den Speicher zu vergrößern.

Das betreffende XML hat die Form einer Liste mit einer Reihe von "" - Tags, die unter dem "" - Tag hängen. Es scheint, dass es auch ein Aufnahmeformat ist.

<root>
    <item>...</item>
    <item>...</item>
    ...
    <item>...</item>
</root>

Bei der Verarbeitung jedes "Elements" hat dies nichts mit anderen "Elementen" zu tun, und es ist gut, sie einzeln zu betrachten. Viele von Ihnen wissen, dass die Verwendung von "Iterator (Generator)" speicherfreundlich ist, wenn diese Art von Daten sehr groß ist. Natürlich haben Bibliotheken, die XML verarbeiten, auch Methoden, mit denen XML-Dateien mit dem Iterator gelesen werden können, aber das war etwas schwierig.

XML in der Python-Standardbibliothek

Es ist einfach, den Standard "xml.etree.ElementTree" zu verwenden, wenn Sie mit XML in Python arbeiten. Es gibt auch ein berühmtes Dokoro BeautifulSoup, aber es wird mit XML analysiert, das ich verarbeiten möchte, weil es auf HTML spezialisiert ist. Es gibt einen Teil, der einen Fehler verursacht [^ 1], und ich bin süchtig danach, also habe ich mich für die Standardbibliothek entschieden. Dieser Artikel beschreibt die Vorsichtsmaßnahmen, die beim Durchführen einer Iterator-XML-Analyse mit dieser Standardbibliothek "XML" zu treffen sind.

Normaler Gebrauch (alles in den Speicher legen)

Dies ist der Fall, wenn Sie es normal verwenden, ohne "Iterator" zu verwenden.

import xml.etree.ElementTree as ET

tree = ET.parse('path/to/xml')

for item in tree.iterfind('item'):
    # do something on item

Sie lesen das Tag "" im XML-Baum mit ".iterfind ()", während "iterator". Aber kurz davor ist "ET.parse ()" wie "file.readlines ()". Ich esse viel Gedächtnis.

Wenn iter (aber Essen essen)

Dies ist, wenn Sie lesen möchten, während "iter".

import xml.etree.ElementTree as ET

context = ET.iterparse('path/to/xml')

for event, elem in context:
    if elem.tag == 'item':
        # do something on item

Wenn "ET.parse ()" in "ET.iterparse ()" geändert wird, wird das XML im Argumentpfad im "Iterator" -Format gelesen. Ich lese es Tag für Tag, aber "context" gibt "event" und "elem" nur zurück, wenn es das Ende des Tags erreicht. Mit event ==" end " ist elem ein Element, nicht wahr?

Jetzt können Sie Speicherplatz sparen! Wenn Sie darüber nachdenken, ist es ein großer Fehler. Selbst wenn "# etwas für einen Gegenstand tun" "bestanden" ist, verbraucht es tatsächlich so viel Speicher wie "normale Verwendung" **.

** iter, aber context speichert alle Tags, die Sie bisher gelesen haben **.

Irgendwo ist eine lokale Variable namens "context.root" im Iterator versteckt. Das wusste ich nicht, weil ich es nicht einmal in die offizielle Dokumentation geschrieben habe. Vielleicht sind manche Menschen in dem Sinne glücklich, dass sie später wiederholt aufgerufen werden können, im Gegensatz zum üblichen "Generator". Nun, ich kann mir vorstellen, dass ein solcher Mechanismus notwendig ist, um die verschachtelte Struktur von XML zu lesen und zu halten.

Wenn iter (kein Gedächtnis essen)

Was soll ich dann tun? Tipps auf der offiziellen Seite, bevor es vor langer Zeit als Bibliothek mit dem Namen "ElementTree" in Python 2.5 in den Standard aufgenommen wurde. hätten. Python war ein Neuling ab 3, also habe ich es überhaupt nicht gemacht.

import xml.etree.ElementTree as ET

context = ET.iterparse('path/to/xml', events=('start', 'end'))

_, root = next(context)  #Gehen Sie noch einen Schritt weiter und wurzeln Sie

for event, elem in context:
    if event == 'end' and elem.tag == 'item':
        # do something on item
        root.clear()  #Leere Wurzel, wenn du fertig bist

Sie können das Schlüsselwortargument "events" in "ET.iterparse ()" angeben. Wenn Sie hierfür "start" angeben, wird das Eröffnungs-Tag angezeigt. Das erste offene Tag ist "". Speichern Sie dieses Tag für die Variable. Zu diesem Zeitpunkt enthält der von "_" verworfene Wert die Zeichenfolge "Start".

Wenn Sie root [^ 2] nehmen, können Sie die Elementinformationen jedes Mal mit .clear () aus dem Speicher holen. Ich bin glücklich.


[^ 1]: Wenn ein einzelnes Tag wie "", das in HTML reserviert ist, in XML verwendet wird, wird es gelöscht, auch wenn sich Text darin befindet. Es gab wahrscheinlich eine Problemumgehung, aber ich erinnere mich, dass es nicht funktioniert hat.

[^ 2]: Klingt nach Android vor langer Zeit und ist wunderbar.

Recommended Posts

So sparen Sie Speicher, wenn Sie in Python großes XML mit mehreren GB oder mehr lesen
[Python] Extrahieren Sie Textdaten aus XML-Daten von 10 GB oder mehr.
So überprüfen Sie die Speichergröße einer Variablen in Python
So überprüfen Sie die Speichergröße eines Wörterbuchs in Python
So formatieren Sie eine Liste von Wörterbüchern (oder Instanzen) in Python
Zusammenfassung zum Importieren von Dateien in Python 3
So implementieren Sie Shared Memory in Python (mmap.mmap)
Zusammenfassung der Verwendung von MNIST mit Python
So ermitteln Sie die Anzahl der Stellen in Python
So messen Sie die Verarbeitungszeit mit Python oder Java
Beenden bei Verwendung von Python in Terminal (Mac)
So entwickeln Sie in einer virtuellen Python-Umgebung [Memo]
Vergleich der Verwendung von Funktionen höherer Ordnung in Python 2 und 3
So erhalten Sie eine Liste der integrierten Ausnahmen für Python
Wie man in Python entwickelt
Schlafverarbeitung für einen bestimmten Zeitraum (Sekunden) oder länger in Python
Wie man Japanern nicht entgeht, wenn man mit json in Python umgeht
So bestimmen Sie die Existenz eines Selenelements in Python
Wie Sie die interne Struktur eines Objekts in Python kennen
So machen Sie einen String in Python zu einem Array oder ein Array zu einem String
So vermeiden Sie doppelte Daten bei der Eingabe von Python in SQLite.
[Anfängernotiz] So legen Sie den Lesepfad der Bibliothek in Python fest
[Python] Wie man PCA mit Python macht
So sammeln Sie Bilder in Python
Verwendung von SQLite in Python
Wie man MySQL mit Python benutzt
So verpacken Sie C in Python
Verwendung von ChemSpider in Python
Verwendung von PubChem mit Python
Umgang mit Japanisch mit Python
So beheben Sie den Fehler "Kein Kernel der Grammatik Python gefunden" in Atom
So blenden Sie die Eingabeaufforderung aus, wenn Sie Python in Visual Studio 2015 ausführen
So senden Sie ein visualisiertes Bild der in Python erstellten Daten an Typetalk
[Python] So fügen Sie eine beliebige Anzahl von Standardeingaben in die Liste ein
Umgang mit SSL-Fehlern beim Herstellen einer Verbindung zu S3 mit Python boto
So schreiben Sie eine Zeichenfolge, wenn Python mehrere Zeilen enthält
[Python] So öffnen Sie zwei oder mehr Dateien gleichzeitig
[Python] Zusammenfassung der Verwendung von Pandas
[Einführung in Python] Wie verwende ich eine Klasse in Python?
Dynamisches Definieren von Variablen in Python
So machen Sie R chartr () in Python
[Itertools.permutations] So löschen Sie eine Sequenz in Python
So arbeiten Sie mit BigQuery in Python
Wie bekomme ich Stacktrace in Python?
So zeigen Sie die neunundneunzig Tabelle in Python an
So extrahieren Sie einen Polygonbereich in Python
Wenn Sie sich die Speichernutzung in Python 3 ansehen
So überprüfen Sie die Version von opencv mit Python
[Python2.7] Zusammenfassung der Verwendung von unittest
So wechseln Sie die Python-Version in Cloud9
So passen Sie den Bildkontrast in Python an
Verwendung von __slots__ in der Python-Klasse
So füllen Sie mit Python dynamisch Nullen aus
Nicht logische Operatorverwendung von oder in Python
Zusammenfassung der Verwendung der Python-Liste
Verwendung regulärer Ausdrücke in Python
[Python2.7] Zusammenfassung der Verwendung des Unterprozesses
So zeigen Sie Hello World in Python an
Verwendung ist und == in Python