Frage

Ich habe ein XML-Dokument in über einen Sockel kommen, die ich brauche on the fly zu analysieren und darauf zu reagieren (dh einen Teilbaum Parsing). Was ich möchte, ist eine nicht blockierende Methode, dies zu tun, so dass ich andere Dinge tun kann, während auf weitere Daten warten zu kommen (ohne Gewinde).

So etwas wie iterparse wäre ideal, wenn es Iterieren beendet, wenn der Lesepuffer leer war, zum Beispiel:

context = iterparse(imaginary_socket_file_wrapper)
while 1:
    for event, elem in context:
        process_elem(elem)
    # iteration of context finishes when socket has no more data
    do_other_stuff()
    time.sleep(0.1)

Ich denke, SAX wäre auch eine Option sein, aber iterparse scheint nur einfacher für meine Bedürfnisse. Irgendwelche Ideen?

Update:

Threads ist in Ordnung, aber stellt ein Maß an Komplexität, die ich zu umgehen hoffte auf. Ich dachte, dass nicht-blockierende Anrufe ein guter Weg sein würde, dies zu tun, aber ich finde, dass es die Komplexität der Parsen der XML erhöht.

War es hilfreich?

Lösung

Tauchen in die iterparse Quelle bereitgestellt, um die Lösung für mich. Hier ist ein einfaches Beispiel für den Aufbau eine XML-Struktur im laufenden Betrieb und die Verarbeitung Elemente nach ihren engen Tags:

import xml.etree.ElementTree as etree

parser = etree.XMLTreeBuilder()

def end_tag_event(tag):
    node = self.parser._end(tag)
    print node

parser._parser.EndElementHandler = end_tag_event

def data_received(data):
    parser.feed(data)

In meinem Fall endete ich es Daten aus verdreht Fütterung, aber es sollte auch mit einem nicht blockierenden Socket arbeiten.

Andere Tipps

Ich denke, es gibt zwei Komponenten dazu, die nicht-blockierende Netzwerk-I / O und einen stromorientierten XML-Parser.

Für den ehemaligen, würden Sie einen non-blocking-Netzwerk Rahmen auswählen müssen, oder rollen Sie Ihre eigene Lösung. Twisted sicher funktionieren würde, aber ich persönlich Inversion of Control Frameworks schwierig finden, mein Gehirn herum zu wickeln. Sie müßten wahrscheinlich Spur eine Menge Zustand in Ihrem Rückruf halten die Parser zu füttern. Aus diesem Grund sind in der Regel finde ich Eventlet ein bisschen leichter zu programmieren, und ich denke, es würde passen gut in dieser Situation .

Im Wesentlichen erlaubt es Ihnen, Ihren Code zu schreiben als ob Sie eine blockierende Socket-Aufruf wurden unter Verwendung (eines gewöhnlichen Schleife oder einen Generator oder was auch immer Sie verwenden), mit der Ausnahme, dass man es in eine separate laichen können Koroutine (a „Greenlet“), die ein kooperatives Ausbeute automatisch durchführen wird, wenn I / O-Operationen blockieren würden, so dass andere Koroutinen auszuführen.

Dies macht jeden stromorientierte Parser trivial wieder verwenden, da der Code wie ein gewöhnlicher blockierenden Anruf aufgebaut ist. Es bedeutet auch, dass viele Bibliotheken, die nicht direkt mit Steckdosen oder andere I / O (wie der Parser zum Beispiel) beschäftigen sie nicht speziell modifiziert werden müssen, um nicht blockierend zu sein. Wenn sie blockieren, Eventlet ergibt die Koroutine

Zugegeben Eventlet ist leicht Magie, aber ich finde es hat eine viel einfachere Lernkurve als Verdreht, und die Ergebnisse in einfacher Code, weil Sie müssen, um nicht schalten Sie Ihre Logik „inside out“ passen den Rahmen.

Wenn Sie nicht Threads verwenden, können Sie eine Ereignisschleife verwenden und abfragen, nicht-blockierende Sockets.

asyncore ist das Standard-Bibliothek-Modul für solche Sachen. Verdrehte ist die Asynchron-Bibliothek für Python, aber komplex und wahrscheinlich ein bisschen Schwergewicht für Ihre Bedürfnisse.

Alternativ multiprocessing ist die nicht-Thread Thread Alternative, aber ich nehme an, Sie sind nicht 2.6 ausgeführt wird.

Eine oder andere Weise, ich denke, du wirst Threads verwenden müssen, zusätzliche Prozesse oder eine ebenso komplexe async Magie weben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top