Jak wspomniano w odpowiedzi Kevina Guerry, strategia "root.clear()" w dokumentacji ElementTree usuwa tylko w pełni sparsowane dzieci z korzenia. Jeśli te dzieci kotwiczą ogromne gałęzie, nie jest to zbyt pomocne.
Dotknął on idealne rozwiązanie, ale nie dodawać żadnego kodu, więc tutaj jest przykład:
element_stack = []
context = ET.iterparse(stream, events=('start', 'end'))
for event, elem in context:
if event == 'start':
element_stack.append(elem)
elif event == 'end':
element_stack.pop()
# see if elem is one of interest and do something with it here
if element_stack:
element_stack[-1].remove(elem)
del context
Element zainteresowania nie będą miały elementy podrzędne; zostaną usunięte, gdy tylko zostaną wyświetlone ich znaczniki końcowe. Może to być OK, jeśli potrzebujesz tylko tekstu lub atrybutów elementu.
Jeśli chcesz zapytać o potomków elementu, musisz utworzyć dla niego pełną gałąź. W tym celu należy zachować flagę, zaimplementowaną jako licznik głębokości dla tych elementów. Wywołuj tylko .remove(), gdy głębokość wynosi zero:
element_stack = []
interesting_element_depth = 0
context = ET.iterparse(stream, events=('start', 'end'))
for event, elem in context:
if event == 'start':
element_stack.append(elem)
if elem.tag == 'foo':
interesting_element_depth += 1
elif event == 'end':
element_stack.pop()
if elem.tag == 'foo':
interesting_element_depth -= 1
# do something with elem and its descendants here
if element_stack and not interesting_element_depth:
element_stack[-1].remove(elem)
del context
Proszę wyjaśnić "zawsze rosnące". Jeśli wykonasz powyższe czynności w pętli, czy użycie pamięci eksploduje? A może widzisz, że użycie wzrasta po zrobieniu tego jeden raz, nawet po uwolnieniu wszystkich obiektów? – wberry
Mam na myśli to, że spodziewam się, że użycie pamięci dla powyższego programu pozostanie stałe. Zamiast tego pokazuje monotyczny wzrost. –
uruchamianie powyższego w pętli nie ma żadnego efektu, ponieważ po prostu zużywa stdin. –