Tengo un gran archivo de datos XML (> 160M) para procesar, y parece que el análisis SAX/expat/pulldom es el camino a seguir. Me gustaría tener un hilo que revise los nodos y empuje los nodos para que se procesen en una cola, y luego otros hilos de trabajo extraen el siguiente nodo disponible de la cola y lo procesan.¿Cómo puedo procesar xml asincrónicamente en python?
tengo el siguiente (debe tener cerraduras, sé - que, más adelante)
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)
El problema es que el cuerpo del bloque while
se llama sólo una vez, y entonces no puedo incluso ctrl-C lo interrumpe. En archivos más pequeños, el resultado es el esperado, pero eso parece indicar que solo se llama al controlador cuando el documento está completamente analizado, lo que parece frustrar el propósito de un analizador SAX.
Estoy seguro de que es mi propia ignorancia, pero no veo dónde estoy cometiendo el error.
PS: Yo también intentó cambiar start_handler
así:
def start_handler(name, attrs):
def app():
q.append(name)
u = threading.Thread(group=None, target=app)
u.start()
Sin amor, sin embargo.
Has votado por las sugerencias de cola, pero ¿estás seguro de que ParseFile traga todo de una vez? Devuelve la llamada a los manejadores de Python para manejar las etiquetas a medida que avanza, ese es el propósito del análisis SAX ... ¿o estás diciendo que eso no es suficiente para activar un cambio de hilo en Python? –
Si desea SAX, puede usar xml.sax, consulte http://docs.python.org/library/xml.sax.html?highlight=sax#module-xml.sax; el OP no usa SAX, sino más bien xml.parsers.expat, una interfaz de baja abstracción que ** no ** impone una estrategia incremental (lo'supports_ it, pero no _impose_ it, dejándolo hasta el nivel de código de Python escoger y elegir). –
La elección de expatriado fue algo arbitraria, no pude encontrar una buena explicación de la diferencia entre expatriados y saxofones. El módulo de saxo funciona igual de bien, incluso mejor, ya que parece ser tan asíncrono como lo necesitaba. Terminé adoptando el método de "alimentarlo por partes" de todos modos, ya que me da la oportunidad de esterilizar las cadenas que alimento antes de que el analizador llegue a ellas. Muy útil respuesta, gracias. – decitrig