xml.etree.cElementTree
подходит к генератору с правильным использованием; по умолчанию вы получаете каждый элемент после события «end», после чего вы можете его обработать. Вы должны использовать element.clear() для элемента, если он не понадобится после обработки; тем самым вы сохраняете память.
Вот полный пример того, что я имею в виду, когда я разбираю библиотеку Rhythmbox (Music Player). Я использую (c) iterparse ElementTree и для каждого обработанного элемента я вызываю element.clear(), так что я сохраняю довольно много памяти. (Btw, нижеприведенный код является преемником некоторого кода саксофона, чтобы сделать то же самое, решение cElementTree было облегчением, так как 1) Код сжатый и выражает то, что мне нужно, и не более 2) Он 3 раза быстрее, 3) она использует меньше памяти.)
import os
import xml.etree.cElementTree as ElementTree
NEEDED_KEYS= set(("title", "artist", "album", "track-number", "location",))
def _lookup_string(string, strmap):
"""Look up @string in the string map,
and return the copy in the map.
If not found, update the map with the string.
"""
string = string or ""
try:
return strmap[string]
except KeyError:
strmap[string] = string
return string
def get_rhythmbox_songs(dbfile, typ="song", keys=NEEDED_KEYS):
"""Return a list of info dictionaries for all songs
in a Rhythmbox library database file, with dictionary
keys as given in @keys.
"""
rhythmbox_dbfile = os.path.expanduser(dbfile)
lSongs = []
strmap = {}
# Parse with iterparse; we get the elements when
# they are finished, and can remove them directly after use.
for event, entry in ElementTree.iterparse(rhythmbox_dbfile):
if not (entry.tag == ("entry") and entry.get("type") == typ):
continue
info = {}
for child in entry.getchildren():
if child.tag in keys:
tag = _lookup_string(child.tag, strmap)
text = _lookup_string(child.text, strmap)
info[tag] = text
lSongs.append(info)
entry.clear()
return lSongs
Теперь, я не понимаю ваших ожиданий, у вас есть следующие ожидания?
# take one
for event, entry in ElementTree.iterparse(rhythmbox_dbfile):
# parse some entries, then exit loop
# take two
for event, entry in ElementTree.iterparse(rhythmbox_dbfile):
# parse the rest of entries
Каждый раз, когда вы вызываете iterparse, вы получаете новый объект итератора, считывая файл заново! Если вы хотите постоянный объект с итераторными семантиками, вы должны ссылаться на тот же объект в обеих петлях (непроверенный код):
#setup
parseiter = iter(ElementTree.iterparse(rhythmbox_dbfile))
# take one
for event, entry in parseiter:
# parse some entries, then exit loop
# take two
for event, entry in parseiter:
# parse the rest of entries
Я думаю, что это может привести к путанице, так как различные объекты имеют различную семантику. Объект файла всегда будет иметь внутреннее состояние и продвигаться в файле, однако вы повторяете его. Объект ElementTree iterparse, по-видимому, нет. Суть заключается в том, чтобы думать, что, когда вы используете цикл for, for всегда вызывает iter() на том, что вы перебираете. Вот эксперимент сравнения ElementTree.iterparse с объектом файла:
>>> import xml.etree.cElementTree as ElementTree
>>> pth = "/home/ulrik/.local/share/rhythmbox/rhythmdb.xml"
>>> iterparse = ElementTree.iterparse(pth)
>>> iterparse
<iterparse object at 0x483a0890>
>>> iter(iterparse)
<generator object at 0x483a2f08>
>>> iter(iterparse)
<generator object at 0x483a6468>
>>> f = open(pth, "r")
>>> f
<open file '/home/ulrik/.local/share/rhythmbox/rhythmdb.xml', mode 'r' at 0x4809af98>
>>> iter(f)
<open file '/home/ulrik/.local/share/rhythmbox/rhythmdb.xml', mode 'r' at 0x4809af98>
>>> iter(f)
<open file '/home/ulrik/.local/share/rhythmbox/rhythmdb.xml', mode 'r' at 0x4809af98>
То, что вы видите, что каждый вызов ИТЭР() на iterparse объекта возвращает новый генератор. Однако объект-файл имеет внутреннее состояние операционной системы, которое должно быть сохранено, и это его собственный итератор.
вот что я хочу ... Я не против «реагировать» на такие события, как «начальный тег» и т. Д. – jldupont
@ Жан-Лу: если вам не нужно все дерево, то SAX - это путь. Он предназначен для обработки документов как поток событий вместо дерева контента. –