【问题标题】:Python: replacing xml elements with multiprocessingPython:用多处理替换 xml 元素
【发布时间】:2019-11-30 18:33:57
【问题描述】:

我有两个不同的 .xml 文件,我想创建一个程序,用 2.xml 中的子项替换 1.xml 中的子项
1.xml 看起来像这样:

<CATALOG>
   <ITEM>
      <COLOR>11</COLOR>
      <COLORNAME>Black</COLORNAME>
   </ITEM>
   <ITEM>
      <COLOR>41</COLOR>
      <COLORNAME>Aqua</COLORNAME>
   </ITEM>
   <ITEM>
      ...
   </ITEM>
</CATALOG>

2.xml 看起来像这样:

<CODES>
   <ITEM>
      <ITEMTYPE>P</ITEMTYPE>
      <ITEMID>44</ITEMID>
      <COLOR>Black</COLOR>
   </ITEM>
   <ITEM>
      <ITEMTYPE>P</ITEMTYPE>
      <ITEMID>44</ITEMID>
      <COLOR>Blue</COLOR>
   </ITEM>
   <ITEM>
      ...
   </ITEM>
</CODES>

我的目标是得到一个 3.xml 文件,它应该如下所示:

<CODES>
   <ITEM>
      <ITEMTYPE>P</ITEMTYPE>
      <ITEMID>44</ITEMID>
      <COLOR>11</COLOR>
   </ITEM>
   <ITEM>
      <ITEMTYPE>P</ITEMTYPE>
      <ITEMID>44</ITEMID>
      <COLOR>7</COLOR>
   </ITEM>
   <ITEM>
      ...
   </ITEM>
</CODES>

我现在编写了一个脚本,将 1.xml 的 &lt;COLOR&gt; 更改为 2.xml 的 &lt;COLOR&gt;,并将 2.xml 中的 &lt;COLORNAME&gt; 与 1.xml 中的 &lt;COLOR&gt; 进行比较

import xml.etree.ElementTree as ET

codes = ET.parse('./datasets/1.xml')
root_codes = codes.getroot()

colors = ET.parse('./datasets/2.xml')
root_colors = colors.getroot()
done=0

for colorname in root_codes.findall('ITEM'):
    codes_color_name = colorname.find('COLOR').text
    for color in root_colors.iter('ITEM'):
        color_name = color.find('COLORNAME').text
        if codes_color_name == color_name:
            color_id = color.find('COLOR').text
            colorname.find('COLOR').text = str(color_id)
            codes.write('3.xml')
            done=done+1
    print(done)

我尝试使用 1.xml 的精简版本,它似乎可以工作。由于这真的很慢(1.xml ~300k 行和 2.xml ~3k 行)我尝试使用多处理,这就是我想出的:

import xml.etree.ElementTree as ET
from multiprocessing import Pool
import multiprocessing
import os

codes = ET.parse('./datasets/1.xml')
root_codes = codes.getroot()

colors = ET.parse('./datasets/2.xml')
root_colors = colors.getroot()

def process_item(colorname):
    codes_color_name = colorname.find('COLOR').text
    for color in root_colors.iter('ITEM'):
        color_name = color.find('COLORNAME').text
        if codes_color_name == color_name:
            color_id = color.find('COLOR').text
            colorname.find('COLOR').text = str(color_id)
            codes.write('3.xml')
            break
if __name__ == '__main__':
    pool = Pool(os.cpu_count())
    pool.map(process_item, root_codes.findall('ITEM'))

我用 1.xml 的精简版试过这个,它基本上吐出相同的文件,没有任何改变。有没有更有效的方法来做到这一点,或者我使用多处理的方式有什么问题?

【问题讨论】:

    标签: python xml multiprocessing python-multiprocessing xml.etree


    【解决方案1】:

    使用多处理是另一回事。让我们首先专注于优化它。

    代码在这里的工作方式实际上是做了很多不必要的处理,比如每次从 1.xml 中查找颜色的值,同时可以预先存储和使用。另外,在更新时,每次都在 2.xml 中查找要更新的颜色,这里可以避免这两种搜索,只需简单的遍历即可解决问题。

    因此,可以做些什么来实现这一点,即维护一对字典(color_name,color_code)。这个 dict 可以通过完全遍历 1.xml 一次来完成,然后在准备好这个 dict 之后,可以遍历 2.xml 的元素,并且可以从 dict 中获取每个元素的颜色代码值,并在更新所有的颜色代码之后2.xml的元素可以存储在3.xml中

    import xml.etree.ElementTree as ET
    
    codes = ET.parse('./datasets/1.xml')
    root_codes = codes.getroot()
    
    colors = ET.parse('./datasets/2.xml')
    root_colors = colors.getroot()
    done=0
    
    color_code_dict = {}
    for color_item in root_colors.iter('ITEM'):
        color_code = color_item.find('COLOR').text
        color_name = color_item.find('COLORNAME').text
        color_code_dict[color_name] = color_code
    
    
    for code_item in root_codes.iter('ITEM'):
        code_color = code_item.find('COLOR').text
        code_item.find('COLOR').text = color_code_dict.get(code_color)
    
    codes.write('3.xml')
    print("Done")
    

    P.S.:确保从写入文件中获取颜色和代码。

    【讨论】:

      猜你喜欢
      • 2015-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-18
      • 2021-10-31
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多