Ho un grande file di dati XML (> 160M) da elaborare e sembra che l'analisi SAX/expat/pulldom sia la strada da percorrere. Mi piacerebbe avere una discussione che passa attraverso i nodi e spinge i nodi per essere elaborati in una coda, e quindi altri thread di lavoro estraggono il successivo nodo disponibile dalla coda e lo elaborano.Come posso elaborare xml in modo asincrono in python?
Ho la seguente (che dovrebbe avere serrature, so - lo farà, in seguito)
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)
Il problema è che il corpo del blocco while
viene chiamato solo una volta, e poi non posso anche Ctrl-C lo interrompe. Su file più piccoli, l'output è come previsto, ma ciò sembra indicare che il gestore viene chiamato solo quando il documento è completamente analizzato, il che sembra vanificare lo scopo di un parser SAX.
Sono sicuro che è la mia ignoranza, ma non vedo dove sto facendo l'errore.
PS: Ho anche provato a cambiare start_handler
così:
def start_handler(name, attrs):
def app():
q.append(name)
u = threading.Thread(group=None, target=app)
u.start()
No amore, però.
Votato per i suggerimenti della coda, ma sei sicuro riguardo a ParseFile che degusta tutto in una volta sola? Richiama i gestori Python per gestire i tag mentre va, questo è l'intero scopo dell'analisi SAX ... o stai dicendo che non è sufficiente per attivare un cambio di thread in Python? –
Se si desidera SAX, è possibile utilizzare xml.sax, consultare http://docs.python.org/library/xml.sax.html?highlight=sax#module-xml.sax; l'OP non sta usando SAX, ma piuttosto xml.parsers.expat, un'interfaccia di astrazione inferiore che ** non ** impone una strategia incrementale (lo supporta, ma non la impone, lasciandola fino al livello di codice Python scegliere e scegliere). –
La scelta di expat è stata alquanto arbitraria, non sono riuscito a trovare una buona spiegazione della differenza tra expat e sax. Il modulo sax funziona altrettanto bene - forse anche meglio, dal momento che sembra essere asincrono come mi serviva. Ho finito con l'adottare il metodo "alimentalo un po 'alla volta" in ogni caso, dal momento che mi dà la possibilità di sterilizzare gli archi che alimento prima che il parser arrivi loro. Risposta molto utile, grazie. – decitrig