【问题标题】:Removing Elements From 300MG Xml In Python / Element Tree在 Python / 元素树中从 300MG Xml 中删除元素
【发布时间】:2015-09-30 09:51:37
【问题描述】:

我正在尝试根据 Can Python xml ElementTree parse a very large xml file? 之类的建议在 ElementTree 中解析一个 300MB 的 XML

from xml.etree import ElementTree as Et

for event, elem in Et.iterparse('C:\...path...\desc2015.xml'):  
    if elem.tag == 'DescriptorRecord':
        for e in elem._children:
            if str(e.tag) in ['DateCreated', 'Year', 'Month', 'TreeNumber', 'HistoryNote', 'PreviousIndexing']:
                e.clear()
                elem.remove(e)
                print 'removed %s' % e

给予...

removed <Element 'HistoryNote' at 0x557cc7f0>
removed <Element 'DateCreated' at 0x557fa990>
removed <Element 'HistoryNote' at 0x55809af0>
removed <Element 'DateCreated' at 0x5580f5d0>

但是,这一直在进行,文件并没有变小,并且经过检查,这些元素仍然存在。尝试了 e.clear() 或 elem.remove(e),但结果相同。问候

更新

我对@alexanderlukanin13 的回答的第一条评论中的错误代码:

Traceback(最近一次调用最后):文件“C:\Users\Eddie\Downloads\eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\pydevd.py”,第 1570 行,在 trace_dispatch Traceback (最近一次通话最后):文件“C:\Users\Eddie\Downloads\eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\pydevd.py”,第 2278 行,在 globals = debugger.run(setup[ 'file'],无,无)文件“C:\Users\Eddie\Downloads\eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\pydevd.py”,第 1704 行,运行 pydev_imports.execfile( file, globals, locals) # 执行脚本 File "C:\Users\Eddie\Downloads\eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\runfiles.py", line 234, in main() File "C:\Users\Eddie\Downloads\eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\runfiles.py", line 78, in main return pydev_runfiles.main(configuration) # 注意:仍然没有返回一个合适的值。主 PydevTestRunner(configuration).run_tests() 文件“C:\ Users\Eddie\Downloads\eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\pydev_runfiles.py",第 762 行,在 run_tests file_and_modules_and_module_name = self.find_modules_from_files(files) File "C:\Users\Eddie\Downloads \eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\pydev_runfiles.py”,第 517 行,在 find_modules_from_files mod = self.__get_module_from_str(import_str, print_exception, pyfile) 文件“C:\Users\Eddie\Downloads\ eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\pydev_runfiles.py",第 476 行,在 __get_module_from_str buf_err = pydevd_io.StartRedirect(keep_original_redirection=True, std='stderr') 文件“C:\Users\Eddie \Downloads\eclipse\plugins\org.python.pydev_4.0.0.201504132356\pysrc\pydevd_io.py",第 72 行,在 StartRedirect import sys MemoryError 中

【问题讨论】:

  • “文件没有变小” - 为什么会这样?您正在更改内存中的对象,这不会更改文件。 300MB 也不算大。

标签: python xml parsing elementtree removechild


【解决方案1】:

脚本中的主要问题是您没有将更改的 XML 保存回磁盘。您需要存储对根元素的引用,然后调用ElementTree.write

from xml.etree import ElementTree as Et

context = Et.iterparse('input.xml')
root = None
for event, elem in context:
    if elem.tag == 'DescriptorRecord':
        for e in list(elem.getchildren()):  # Don't use _children, it's a private field
            if e.tag in ['DateCreated', 'Year', 'Month', 'TreeNumber', 'HistoryNote', 'PreviousIndexing']:
                elem.remove(e)  # You need remove(), not clear()
    root = elem

with open('output.xml', 'wb') as file:
    Et.ElementTree(root).write(file, encoding='utf-8', xml_declaration=True)

注意:这里我使用了一种尴尬(而且可能不安全)的方式来获取根元素——我假设它始终是iterparse 输出中的最后一个元素。如果有人知道更好的方法,请告诉。

【讨论】:

  • 非常感谢@alexanderlukanin13。这就是我所追求的。从 Eclipse 尝试了两次:第一次花了 20m 并给出了内存错误(如下),第二次崩溃了 Python。台式机是 16GB 四核 3.4GHz。非常感谢您提供更多见解。
  • @user2422819 DOM 解析注定要消耗大量内存并最终在某些 XML 大小上失败。但坦率地说,我没想到在 300MB 上会失败。 1) 尝试从命令行运行它,也许 Eclipse+调试器有干扰 2) 考虑移动到内存要求较低的xml.sax。您可以从this example 开始并对其进行自定义以支持嵌套元素逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多