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 "
<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.
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.
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 "
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.
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 "
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