如何在 Python 解析过程中处理内存错误?

我遇到了内存错误,我正在尝试为这个问题找到最佳解决方案。基本上我通过同一类的多个线程下载了很多 XML 文件。我的班级使用以下命令下载文件:


urlretrieve(link, filePath)

我将下载文件的路径保存到线程之间同步的队列中。


downloadedFilesQ.put(filePath)

在另一个类(也是多个线程)中,我尝试解析这些 XML 文件并将它们保存为 Python 对象,以便将来保存在数据库中。我正在使用以下命令来解析文件:


    xmldoc = minidom.parse(downloadedFilesQg.get())

下载和解析流程同时运行。下载流程在大约 2 分钟后完成,而解析流程大约需要 15 分钟。15 分钟后,我在以下行出现内存错误:


Exception in thread XMLConverterToObj-21:

Traceback (most recent call last):

  File "C:\Users\myuser\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 926, in _bootstrap_inner

    self.run()

  File "C:\Users\myuser\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 870, in run

    self._target(*self._args, **self._kwargs)

  File "C:\Users\myuser\PycharmProjects\weat\Parsers\ParseXML.py", line 77, in parseXML

    xmldoc = minidom.parse(xml_file)

  File "C:\Users\myuser\AppData\Local\Programs\Python\Python37-32\lib\xml\dom\minidom.py", line 1958, in parse

    return expatbuilder.parse(file)

  File "C:\Users\myuser\AppData\Local\Programs\Python\Python37-32\lib\xml\dom\expatbuilder.py", line 911, in parse

    result = builder.parseFile(fp)

  File "C:\Users\myuser\AppData\Local\Programs\Python\Python37-32\lib\xml\dom\expatbuilder.py", line 207, in parseFile

    parser.Parse(buffer, 0)

  File "c:\_work\16\s\modules\pyexpat.c", line 417, in StartElement

  File "C:\Users\myuser\AppData\Local\Programs\Python\Python37-32\lib\xml\dom\expatbuilder.py", line 746, in start_element_handler

    _append_child(self.curNode, node)

  File "C:\Users\myuser\AppData\Local\Programs\Python\Python37-32\lib\xml\dom\minidom.py", line 291, in _append_child

    childNodes.append(node)

MemoryError


我考虑的选项是,一旦我达到 100K python 对象,将它们保存到数据库,然后再次继续解析。问题是多个业务可以重复,因此我想解析一次所有文件,然后将业务插入到一个集合中(以忽略重复的业务)。


我还有其他可以尝试的方法吗?


小唯快跑啊
浏览 236回答 1
1回答

慕田峪4524236

您似乎同时将所有内容都保存在内存中。然而,计算机使用的内存 RAM 比存储内存(硬盘)要有限得多。因此,您可以轻松地在存储器中存储大量 XML 文档,但不能同时在 RAM 中保存所有内容。在你的情况下,这意味着你应该从根本上改变你的程序。您的程序应该以流方式工作,这意味着它应该加载一个 XML 文档,对其进行解析,以某种方式对其进行处理,将其结果存储在数据库中,然后再次忘记该文档。最后一点对于释放文档占用的 RAM 至关重要。现在您写道,您需要弄清楚哪些文档是重复的。为了实现这一点,我建议不要将整个文档存储在内存中,而只是为每个文档存储一个哈希值。为此,您需要提供一个像样的散列函数,为给定的文档创建一个唯一的散列值。然后你只将你处理的每个文档的哈希值存储在 aset中,每次遇到具有相同哈希值的新文档时,你就会知道这是一个重复的文档并可以相应地处理它(例如忽略它)。虽然在内存中同时保存 7000 个 9MB 大小的文档可能是不可能的,但在内存中同时保存 7000 个哈希值是很容易的。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python