gpt4 book ai didi

python:是否有作为生成器实现的 XML 解析器?

转载 作者:太空狗 更新时间:2023-10-29 20:35:00 25 4
gpt4 key购买 nike

我想“即时”解析一个大的 XML 文件。我想使用 python 生成器来执行此操作。我试过“xml.etree.cElementTree”的“iterparse”(这真的很好)但仍然不是生成器。

其他建议?

最佳答案

xml.etree.cElementTree 接近正确使用的生成器;默认情况下,您会在每个元素的“结束”事件之后收到它,此时您可以对其进行处理。如果在处理后不需要它,你应该在元素上使用 element.clear() ;从而节省内存。


这是我的意思的完整示例,我在其中解析 Rhythmbox 的(音乐播放器)库。我使用 (c)ElementTree 的 iterparse 并为每个处理过的元素调用 element.clear() 以便我节省大量内存。 (顺便说一句,下面的代码是一些 sax 代码的继承者,可以做同样的事情;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 对象的 iter() 调用都会返回一个新的生成器。然而,文件对象有一个必须保存的内部操作系统状态和它自己的迭代器。

关于python:是否有作为生成器实现的 XML 解析器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1513592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com