使用“pythons-etree.iterparse()”解析大型xml文件不正常。代码中有逻辑错误吗?

使用“pythons-etree.iterparse()”解析大型xml文件不正常。代码中有逻辑错误吗?,python,xml,lxml,elementtree,iterparse,Python,Xml,Lxml,Elementtree,Iterparse,我想解析一个巨大的xml文件。这个巨大文件中的记录看起来确实像这样。一般来说,文件是这样的 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE dblp SYSTEM "dblp.dtd"> <dblp> record_1 ... record_n </dblp> 编辑: 当我写这个函数时,我完全被误导了。我犯了一个巨大的错误,我忽略了,当我试图跳过一些不想要的录音时

我想解析一个巨大的xml文件。这个巨大文件中的记录看起来确实像这样。一般来说,文件是这样的

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE dblp SYSTEM "dblp.dtd">
<dblp>
    record_1
    ...
    record_n
</dblp>
编辑: 当我写这个函数时,我完全被误导了。我犯了一个巨大的错误,我忽略了,当我试图跳过一些不想要的录音时,却被一些想要的录音弄得一团糟。在文件中的某一点上,我连续跳过了将近一百万条记录,下面的通缉记录被炸毁了

在约翰和保罗的帮助下,我设法重写了我的代码。它现在正在解析,我们希望能把它做好。如果一些意外的错误仍然没有解决,我会向你汇报。另外,谢谢大家的帮助!我真的很感激

def fast_iter2(context, cursor):
    elements = set([
        'article', 'inproceedings', 'proceedings', 'book', 'incollection',
        'phdthesis', "mastersthesis", "www"
        ])
    childElements = set(["title", "booktitle", "year", "journal", "ee"])

    paper = {} # represents a paper with all its tags.
    authors = []   # a list of authors who have written the paper "together".
    paperCounter = 0
    for event, element in context:
        tag = element.tag
        if tag in childElements:
            if element.text:
                paper[tag] = element.text
                # print tag, paper[tag]
        elif tag == "author":
            if element.text:
                authors.append(element.text)
                # print "AUTHOR:", authors[-1]
        elif tag in elements:
            paper["element"] = tag
            paper["mdate"] = element.get("mdate")
            paper["dblpkey"] = element.get("key")
            # print tag, element.get("mdate"), element.get("key"), event
            if paper["element"] in ['phdthesis', "mastersthesis", "www"]:
                pass
            else:
                populate_database(paper, authors, cursor)
            paperCounter += 1
            print paperCounter
            paper = {}
            authors = []
            # if paperCounter == 100:
            #     break
            element.clear()
            while element.getprevious() is not None:
                del element.getparent()[0]
    del context

在检测元素中标记的开始和停止的代码块中添加print语句,以确保正确地检测到这些标记。我怀疑由于某种原因,您没有找到清除作者列表的代码

尝试注释此代码(或至少将其移动到“end”处理块):


Python应该在遍历XML时为您清除这些元素。“del上下文”也是多余的。让引用计数器为您完成这里的工作。

请消除一个混淆源:您并没有说您显示的代码实际上在一个“count of things>2000”测试中出错。如果不是,那么问题在于数据库更新代码(您没有向我们展示)

如果这样做,则会绊倒:

(1) 将限制从2000降低到合理值(对于
auth
约为20,对于mydict正好为7)

(2) 当跳闸发生时,
打印报告(mydict);印刷品;打印repr(auth)
并将内容与文件进行比较分析

旁白:对于iterparse(),不能保证在“开始”事件发生时解析elem.text。为了节省一些运行时间,您应该仅在“结束”事件发生时访问elem.text。事实上,似乎根本没有理由想要“开始”活动。您还定义了一个列表
标记
,但从不使用它。函数的开头可以写得更简洁:

def fast_iter(context, cursor):
    mydict = {} # represents a paper with all its tags.
    auth = [] # a list of authors who have written the paper "together".
    counter = 0 # counts the papers
    tagset1 = set(['article', 'inproceedings', 'proceedings', 'book', 'incollection'])
    tagset2 = set(["title", "booktitle", "year", "journal"])
    for event, elem in context:
        tag = elem.tag
        if tag in tagset2:
            if elem.text:
                mydict[tag] = elem.text
        elif tag == "author":
            if elem.text:
                auth.append(elem.text)
        elif tag in tagset1:
            counter += 1
            print counter
            mydict["element"] = tag
            mydict["mdate"] = elem.get("mdate")
            mydict["dblpkey"] = elem.get("key")
            #populate_database(mydict, auth, cursor)
            mydict.clear() # Why not just do mydict = {} ??
            auth = []
            # etc etc
不要忘记修复对iterparse()的调用以删除事件arg


此外,我还可以合理地确定,elem.clear()只应在事件为“end”时执行,并且只需在tagset1中的
标记时执行。仔细阅读。在“开始”事件中进行清理很可能会损坏您的树。

有专门的文档记录,除非您采取特定的操作来清理,否则iterparse()将构建整个树。阅读以下内容:@John-谢谢,我个人并不熟悉iterparse,但我有一种预感,在事件结束前清除元素会把事情搞砸。不过,我必须说,必须清理这些增量变量并不是我所期望的名称以“iter”开头的东西。谢谢你的建议。我修改了它们,更正了问题中的代码,并将其标记为“编辑”。这是一个很好的建议。未分析我的
elem.text
字段,因为我正在分析“开始”事件。寻找“结束”事件解决了这个问题。
    elem.clear()
    while elem.getprevious() is not None:
        del elem.getparent()[0]
def fast_iter(context, cursor):
    mydict = {} # represents a paper with all its tags.
    auth = [] # a list of authors who have written the paper "together".
    counter = 0 # counts the papers
    tagset1 = set(['article', 'inproceedings', 'proceedings', 'book', 'incollection'])
    tagset2 = set(["title", "booktitle", "year", "journal"])
    for event, elem in context:
        tag = elem.tag
        if tag in tagset2:
            if elem.text:
                mydict[tag] = elem.text
        elif tag == "author":
            if elem.text:
                auth.append(elem.text)
        elif tag in tagset1:
            counter += 1
            print counter
            mydict["element"] = tag
            mydict["mdate"] = elem.get("mdate")
            mydict["dblpkey"] = elem.get("key")
            #populate_database(mydict, auth, cursor)
            mydict.clear() # Why not just do mydict = {} ??
            auth = []
            # etc etc