Ich habe eine große XML-Datendatei (> 160M) zu verarbeiten, und es scheint wie SAX/Expat/Pulldom Parsing ist der Weg zu gehen. Ich würde gerne einen Thread haben, der sich durch die Knoten bewegt und Knoten zur Verarbeitung in eine Warteschlange schiebt, und dann ziehen andere Arbeiter-Threads den nächsten verfügbaren Knoten aus der Warteschlange und verarbeiten ihn.Wie kann ich XML in Python asynchron verarbeiten?
Ich habe folgendes (es sollte Schlösser haben, ich weiß - es wird, später)
import sys, time
import xml.parsers.expat
import threading
q = []
def start_handler(name, attrs):
q.append(name)
def do_expat():
p = xml.parsers.expat.ParserCreate()
p.StartElementHandler = start_handler
p.buffer_text = True
print("opening {0}".format(sys.argv[1]))
with open(sys.argv[1]) as f:
print("file is open")
p.ParseFile(f)
print("parsing complete")
t = threading.Thread(group=None, target=do_expat)
t.start()
while True:
print(q)
time.sleep(1)
Das Problem ist, dass der Körper des while
Block nur einmal aufgerufen wird, und dann kann ich nicht sogar Ctrl-C unterbricht es. Bei kleineren Dateien ist die Ausgabe wie erwartet, aber das scheint anzuzeigen, dass der Handler nur aufgerufen wird, wenn das Dokument vollständig geparst ist, was den Zweck eines SAX-Parsers zu besiegen scheint.
Ich bin sicher, es ist meine eigene Ignoranz, aber ich sehe nicht, wo ich den Fehler mache.
PS: Ich habe auch versucht start_handler
so zu ändern:
def start_handler(name, attrs):
def app():
q.append(name)
u = threading.Thread(group=None, target=app)
u.start()
keine Liebe, though.
Sind für die Warteschlangenvorschläge ausgewählt, aber sind Sie sicher, dass ParseFile alles auf einmal verschlingt? Es ruft zurück in die Python-Handler, um die Tags zu behandeln, das ist der ganze Zweck des SAX-Parsens ... oder sagst du, dass das nicht ausreicht, um einen Threadwechsel in Python auszulösen? –
Wenn Sie SAX möchten, können Sie xml.sax verwenden, siehe http://docs.python.org/library/xml.sax.html?highlight=sax#module-xml.sax; Das OP verwendet nicht SAX, sondern eher xml.parsers.expat, eine Schnittstelle mit niedrigerer Abstraktion, die ** keine ** inkrementelle Strategie vorschreibt (sie unterstützt es, aber nicht _implementiert es, so dass sie der Python-Code-Ebene entspricht) auswählen und auswählen). –
Die Wahl des Expats war etwas willkürlich, ich konnte keine gute Erklärung für den Unterschied zwischen Expat und Saxophon finden. Das Sax-Modul funktioniert genauso gut - vielleicht sogar besser, weil es so asynchron zu sein scheint, wie ich es brauchte. Ich entschied mich, die Methode "füttere es ein Stück nach dem anderen" zu verwenden, da es mir die Möglichkeit gibt, die Saiten, die ich füttere, zu sterilisieren, bevor der Parser zu ihnen gelangt. Sehr hilfreiche Antwort, danke. – decitrig