【问题标题】:Only portions of data are being written to a cvs file, rest is missing只有部分数据被写入 csv 文件,其余部分丢失
【发布时间】:2017-04-27 13:40:19
【问题描述】:

我正在解析许多 xml 文件并将某些信息放入 csv 文件中。因为我的 xml 文件被命名为:“1.xml”、“2.xml”等...我正在使用 for 循环来循环浏览不同的 XML 文件标题。但是,根据我在 for 循环中使用的范围,我的 csv 文件包含不同的数据。例如,当我的 for 循环范围为 1:200 时,我的 csv 文件包含我的 xml 文件 1 到 199 的信息。但是,当我将范围更改为 1:300 时,我的 csv 文件只包含我的 xml 文件 217 到 249 的信息. 实际存储在我的 csv 文件中的信息会根据我输入的 for 循环范围而改变。有没有其他人遇到过这个错误,你有什么解决办法吗?

我的代码如下:

import xml.etree.ElementTree as ET
import csv
from pathlib import Path

# open a file for writing

data_labels = open('DataLabels.csv', 'w', newline='')
missing_files = open('MissingFiles.csv', 'w', newline = '')

# create the csv writer object
csvwriter = csv.writer(data_labels)
csvwriter2 = csv.writer(missing_files)
data_head = []
data = []
missingfiles = 0
missfiles = []

MediaId = "Media Id"
    #data_head.append (MediaId)

Family = "Family"
    #data_head.append (Family)

Species = "Species"
    #data_head.append (Species)

Genus = "Genus"
Content = "Content"
ClassId = "ClassId"
    #data_head.append (Genus)

data_head.append(MediaId)
    #   Family = member.find('Family').tag
data_head.append(Content)
data_head.append(ClassId)
data_head.append(Family)
    #   Species = member.find('Species').tag
data_head.append(Species)
    #   Genus = member.find('Genus').tag
data_head.append(Genus)

csvwriter.writerow(data_head)

for i in range (1, 190):
    #print (i)
    data = []

    inputfilename = str(i)+ ".xml"

    my_file = Path(inputfilename)
    if my_file.is_file():

        data_labels = open('DataLabels.csv', 'w', newline='')

        tree = ET.parse(inputfilename)
        root = tree.getroot()

        MediaId = root [2].text
        Content = root[4].text
        ClassId = root[5].text
        Family = root[6].text
        Species = root[7].text
        Genus = root[8].text

        #print (vote)
        #count = 0
        #for Image in root.find('MediaId'):
        #print (child.tag, child.attrib)
        #name = child.find('MediaId').text
    #   print (Image.find ('MediaId').text)
    ##csvwriter.writerow (data_head)

    #data = []

    #if count == 0:
    #   print ("count is zero i'm in loop")
    #   MediaId = member.find('MediaId').tag

    #   count = count + 1
    #else:
    #MediaId = root.findall('MediaId').text
        data.append(MediaId)
        data.append (Content)
        data.append (ClassId)
#Family = member.find('Family').text
        data.append(Family)
#Species = member.find('Species').text
        data.append(Species)
#Genus = member.find('Genus').text
        data.append(Genus)
        csvwriter.writerow(data)
        data_labels.close()
        #print (data)
    else:
        missingfiles = missingfiles +1
        missfiles = []
        missfiles.append(inputfilename)
        csvwriter2.writerow(missfiles)


print ("missing", missingfiles, "files")
data_labels.close()
missing_files.close()

print ("done")

【问题讨论】:

  • 哪个操作系统?我不明白你是如何获得任何数据的。 for 循环内的 data_labels = open('DataLabels.csv', 'w', newline='') 不断覆盖文件。在 linux 上,它将取消您正在写入数据的原始文件的链接。在 Windows 上,这不是共享违规吗? (我没有一台机器来测试那个……)。

标签: python csv xml-parsing


【解决方案1】:

以追加模式打开 csv,否则你只是覆盖了同一个文件。

【讨论】:

  • 非常感谢!做到了!
【解决方案2】:

我认为您需要将脚本划分为小的可读函数。

首先,您可以创建一个函数来解析 XML 文件:

import xml.etree.ElementTree as ET


def parse_xml_file(xml_path):
    """ Parse an XML file and return the data. """
    # type: (str) -> list
    tree = ET.parse(xml_path)
    root = tree.getroot()
    return [
        root[2].text,
        root[4].text,
        root[5].text,
        root[6].text,
        root[7].text,
        root[8].text]

此函数解析一个 XML 文件并返回一个包含值列表的记录。

然后,您可以创建一个函数来迭代 XML 文件(现有文件)列表并填充 CSV 文件:

import csv
import io
import os


def populate_data_labels(xml_path_list, work_dir="."):
    header = ["Media Id", "Family", "Species", "Genus", "Content", "ClassId"]
    with io.open(os.path.join(work_dir, 'DataLabels.csv'), 'w') as fd:
        writer = csv.writer(fd)
        writer.writerow(header)
        for xml_path in xml_path_list:
            writer.writerow(parse_xml_file(xml_path))

此函数使用parse_xml_file() 提取每条记录。

您可以创建一个函数来记录丢失的文件。您可以使用 CSV 格式(或简单的文本文件):

def populate_missing_files(missing_files, work_dir="."):
    header = ["Filename"]
    with io.open(os.path.join(work_dir, 'MissingFiles.csv'), 'w') as fd:
        writer = csv.writer(fd)
        writer.writerow(header)
        for xml_path in missing_files:
            writer.writerow([os.path.basename(xml_path)])

最后,您可以编写一个搜索 XML 文件并调用之前的函数的函数:

def parse_work_dir(work_dir="."):
    all_files = [os.path.join(work_dir, "{0}.xml".format(idx))
                 for idx in range(1, 190)]
    existing_files = (path for path in all_files if os.path.exists(path))
    populate_data_labels(existing_files, work_dir)
    missing_files = (path for path in all_files if not os.path.exists(path))
    populate_missing_files(missing_files, work_dir)

用法:

parse_work_dir("/path/to/your/working/dir")

【讨论】:

  • 我认为你是绝对正确的,我应该将我的代码分成更小的部分,但是考虑到我对编码的新颖性,将它分块编写更容易(我在编写代码时进行了测试)然后创建和调用函数。非常感谢您重构我的代码!
猜你喜欢
  • 1970-01-01
  • 2012-05-05
  • 2019-09-09
  • 2022-05-25
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
  • 2019-09-10
  • 1970-01-01
相关资源
最近更新 更多