python - Python:用多处理替换 xml 元素
问题描述
我有两个不同的 .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 更改<COLOR>
为<COLOR>
2.xml,并将<COLORNAME>
from 2.xml 与<COLOR>
from 1.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
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 的精简版尝试了这个,它基本上吐出相同的文件,没有任何改变。有没有更有效的方法来做到这一点,或者我使用多处理的方式有什么问题?
解决方案
使用多处理是另一回事。让我们首先专注于优化它。
代码在这里的工作方式实际上是在做很多不必要的处理,比如每次从 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")
PS:确保从写入文件中获取颜色和代码。
推荐阅读
- security - 关于随机化堆栈内存地址空间的说明
- python-3.x - 尝试在不使用熊猫的情况下从 txt 文件中添加字段的总和
- c++ - 将 QML 连接到 C++ 插槽
- docker - go 不会从容器中写入文件,除非应用程序是从容器中手动启动的
- python - 从 6 个阅读框中找到最长的 orf
- python - 如何在申请后立即自动向求职者发送电子邮件,odoo 14
- django - 如何修复 Windows10 上的 TemplateDoesNotExist 错误?
- aws-cdk - 如何使用 CDK 将 *all* 机密注入 ECS 任务
- mysql - 一个特定日期和一列之间的 datediff MySQL
- azure-devops - 错误 NETSDK1045:当前的 .NET SDK 不支持面向 .NET 6.0