Was ist der beste Weg, um die Chunk -Größe zu kontrollieren, die von XML -iterativen Parsers in Python verwendet wird, oPython

Python-Programme
Anonymous
 Was ist der beste Weg, um die Chunk -Größe zu kontrollieren, die von XML -iterativen Parsers in Python verwendet wird, o

Post by Anonymous »

Frage: Was ist der beste Weg, um die Chunk -Größe zu kontrollieren, die von Standard -XML -iterativen Parsers in Python verwendet wird? Chunk -Größe zur Verwendung durch iterative Parser, was ist dann die optimale Chunk -Größe? Insbesondere wo sind die ausgewählten Chunk-Größen für die beliebten Bibliotheken Lxml und das integrierte Python integriert. Problemumgehung zum Ändern der Standard -Chunk -Größe (z. B. in einzelnen Zeilen als Beweis für das Konzept), während Sie immer noch dieselben iterativen Parser verwenden und keine neue entwickeln, aber ich möchte wissen, ob es dort ist ist eine bessere, weithin bekannte Lösung als meine etwas hackige Problemumgehung.
* HINWEI Zu einem einzelnen Öffnungs- oder Schlussetikett eines einzelnen Elements ist es denkbar, dass einige Stückgrößen in Bezug auf die Anzahl der Zeilen gemessen werden können. Parsers, die die Größen in der Anzahl von Zeichen messen, ist möglicherweise plausibler. BoilerPlate -Code. Xml.etree.elementtree ) wird diskutiert, es klingt oft so, als ob es XML-Dateien "iterativ" analysiert, wie in Element-by-Element/Tag-by-Tag (siehe Anmerkung oben). < BR /> Aber es scheint, dass in der Praxis ein Datei-ähnliches Objekt als Eingabe angegeben hat und beide Parser die Ausgabe der .read < /code> -Methode dieses Datei-ähnlichen Objekts suchen und analysieren. (Im Gegensatz zur Ausgabe von .readline wie ich erwartet hatte.) Wenn dieses Datei-ähnliche Objekt ein Dateianschluss für eine 8-GB-Datei ist und dies auf einem Clusterknoten mit 2 GB Speicher ausgeführt wird, wird dies natürlich auch sein einen OOM -Fehler verursachen. < /p>

Code: Select all

.read
scheint einen optionalen Parameter n zu haben, der der Anzahl der Zeilen der Dokument-/Textdatei zum Lesen in den Speicher entspricht. Wenn jedoch standardmäßige iterative Parsers diesen optionalen Parameter tatsächlich verwenden Wenn Sie .Read aufrufen, scheinen sie nicht zu dokumentieren, welchen Wert sie verwenden. Das folgende Beispiel von MWE zeigt, dass diese Schlussfolgerung auf dieser Antwort auf eine verwandte Frage sowie meinen eigenen Test basiert, wenn ein solcher Wert verwendet wird, dann ist diese Schlussfolgerung auf dieser Antwort basiert. . Hier ist ein MWE: < /p>

Code: Select all

import io
from lxml import etree
import xml.etree.ElementTree as etree2

xml_string = """







Manager

Star Team Member




"""

#### lxml output

for event, element in etree.iterparse(io.BytesIO(xml_string.encode("UTF-8")), recover=True, remove_blank_text=True,
events=("start", "end",)):
print(str((event, element, element.tag,
element.text.strip() if element.text is not None else element.text,
element.tail.strip() if element.tail is not None else element.tail)) + "\n")
print(f"{etree.tostring(element)}\n")

### xml.etree.ElementTree output is the same

for event, element in etree2.iterparse(io.BytesIO(xml_string.encode("UTF-8")),
events=("start", "end",)):
print(str((event, element, element.tag,
element.text.strip() if element.text is not None else element.text,
element.tail.strip() if element.tail is not None else element.tail)) + "\n")
print(f"{etree2.tostring(element)}\n")

Bereits bei der ersten Iteration stellt die String -Darstellung des Root -Tags das gesamte XML -Dokument dar, was darauf hindeutet als nur die erste Zeile (was ich ursprünglich gedacht hatte, dass die erste Iteration der Diskussion anderer über Iterparse entsprechen sollte. nach unten Problemumgehung, in dem das erwartete Parsingverhalten von Linien für Linie angezeigt wird. Ich frage mich jedoch, ob es bessere Lösungen gibt. Würden beispielsweise die Millionen von Anrufen bei Readline < /code>, die für ~ 8 GB Datei getätigt werden müssten ">### for the MWE

class StreamString(object):

def __init__(self, string):
self._io = io.StringIO(string)

def read(self, len=None):
return self._io.readline().encode("UTF-8")

def close(self):
self._io.close()

### closer to what would be used in practice

class StreamFile(object):

def __init__(self, path):
self._file = open(path, "r")

def read(self, len=None):
return self._file.readline().encode("UTF-8")

def close(self):
self._file.close()

### demonstrating the expected line-by-line parsing behavior

iterator = etree.iterparse(StreamString(xml_string), recover=True, remove_blank_text=True,
events=("start", "end",))
event, root = next(iterator)
print(str((event, root, root.tag,
root.text.strip() if root.text is not None else root.text,
root.tail.strip() if root.tail is not None else root.tail)) + "\n")
print(f"{etree.tostring(root)}\n")

for event, element in iterator:
print(str((event, element, element.tag,
element.text.strip() if element.text is not None else element.text,
element.tail.strip() if element.tail is not None else element.tail)) + "\n")
print(f"{etree.tostring(root)}\n")

< /code>
Dies zeigt das erwartete Verhalten, wobei der Parsen -Baum, der dem Stammelement entspricht, mit jeder Iteration nacheinander wächst, wenn neue Zeilen hinzugefügt werden. Dieses Verhalten ist auch leichter zu verstehen und mit den zahlreichen Vorschlägen auf dieser Seite zu verhindern, wie die Speicher Fußabdrücke, die Knoten und ihren Vorfahren (und all ihren "älteren" Tiefen-First-Suchgeschwistern) entsprechen, nach der Analyse entsprechen. Mir ist unklar, warum dies nicht das Standardverhalten ist. < /P>
Hinweis: Obwohl die für die MWE verwendete XML Für XML-Dateien, die potenziell Gigabyte auf Größe auf Clusterknoten mit 1-2 GB Speicher sind. (Ich habe keine Kontrolle über die Rechenumgebung, ja, ich bin damit einverstanden, dass es sinnvoller ist, einfach vertikal auf einen einzelnen Knoten mit ~ 64 GB Speicher zu skalieren.)

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post