在 python 中使用 Argparse 将 xml 转换为 csv
Posted
技术标签:
【中文标题】在 python 中使用 Argparse 将 xml 转换为 csv【英文标题】:Using Argparse To Convert xml to csv in python 【发布时间】:2013-06-22 12:26:15 【问题描述】:我需要像这样接受一些命令行参数:
argparse.py hi.xml --> to produce hi.csv or
argparse.py hi.xml -o hello.csv --> to produce hello.csv
这是我的代码:
import os
import sys
import argparse
import csv
import indent
from xml.etree.ElementTree import ElementTree, Element, SubElement, Comment, tostring
import xml.etree.ElementTree as etree
def get_args(args):
parser = argparse.ArgumentParser(description = "Converts CSV to XML")
parser.add_argument('-v','--verbose',action='store_true',dest='verbose',help='Increases messages being printed to stdout')
parser.add_argument("inputfile", help="Please input the name of the CSV file")
parser.add_argument('-o','--outputfile',help='(optional) Output file name',nargs='?')
args = parser.parse_args()
ext = os.path.splitext(args.inputfile)[1].lower()
if args.outputfile is None:
if ext == ".csv":
args.outputfile = os.path.splitext(args.inputfile)[0] + '.xml'
elif ext == ".xml":
args.outputfile = os.path.splitext(args.inputfile)[0] + '.csv'
elif args.outputfile:
if ext == ".csv":
outputfile = open(args.outputfile, 'w')
elif ext == ".xml":
outputfile = open(args.outputfile,'w')
else:
sys.stderr.write('ERROR: Invalid extension %s\n' % ext)
sys.exit(1)
return args
def main(argv):
args = get_args(argv[0:])
if args is None:
return 1
ext = os.path.splitext(args.inputfile)[1].lower()
if ext == ".csv":
reader = read_csv(open(args.inputfile))
generate_xml(reader, args.outputfile)
if ext == ".xml":
root = etree.parse(open(args.inputfile)).getroot()
generate_csv(root, args.outputfile)
if args.verbose:
print ('Verbose Selected')
if args.verbose:
print ('Convert to XML with set name')
return 0
def read_csv(inputfile):
return list(csv.reader(inputfile))
def generate_xml(reader,outfile):
root = Element('Solution')
root.set('version','1.0')
tree = ElementTree(root)
head = SubElement(root, 'DrillHoles')
description = SubElement(head,'description')
current_group = None
i = 0
for row in reader:
if i > 0:
x1,y1,z1,x2,y2,z2,cost = row
if current_group is None or i != current_group.text:
current_group = SubElement(description, 'hole','hole_id':"%s"%i)
collar = SubElement (current_group, 'collar','':', '.join((x1,y1,z1))),
toe = SubElement (current_group, 'toe','':', '.join((x2,y2,z2)))
cost = SubElement(current_group, 'cost','':cost)
i+=1
head.set('total_holes', '%s'%i)
indent.indent(root)
tree.write(outfile)
def generate_csv(root, outfile):
with open(outfile, 'w') as file_:
writer = csv.writer(file_, delimiter="\t")
for a in zip(root.findall("drillholes/hole/collar"),
root.findall("drillholes/hole/toe"),
root.findall("drillholes/hole/cost")):
writer.writerow([x.text for x in a])
if (__name__ == "__main__"):
sys.exit(main(sys.argv))
我只需要 generate_csv 部分的帮助。正如您从函数 get_args(args) 中看到的那样,我获得了参数,这也是我使用 ext = ... 更改文件扩展名的地方。然后我使用 return args 将其返回。主函数调用此函数并获取参数,然后再次检查扩展名,然后根据扩展名进入下一个函数。在主函数中,我已经解析了 xml 文件,所以我只需将“root”和“args.outputfile”传递给 generate_csv 方法。然而,这是发生错误的地方: xml.etree.ElementTree.parserError: no element found line 1 column 0. 但是,我相信这可能不是唯一的错误,也许是我将参数传递到某个地方的方式它丢失了或修改的。请帮忙
【问题讨论】:
您不需要将args
传递给您的get_args
函数。 ArgumentParser 类知道从命令行查找参数。您实际上也不需要将 sys.argv
传递给 main。
【参考方案1】:
这并不是一个最小的示例,因此很难准确地确定您的问题是什么以及具体的问题是什么。
错误表示解析器没有输入。这表明文件实际上是空的,或者文件指针已经前进到文件的末尾。如果您不小心打开它进行写入并将其截断为零,则该文件可能为空。如果您不小心打开文件进行读取,从文件中读取所有内容,而忽略了回退文件指针,则文件指针可能会提前到文件末尾。
所以您可以看到发生了什么,为什么不尝试一些诊断程序,该诊断程序会采取婴儿步骤并在其间打印出来?也就是说,不要尝试etree.parse(open(args.inputfile))
,而是尝试以下操作:
print( args.inputfile )
f = open( args.inputfile )
print( f.tell() )
print( f.read() )
f.seek(0)
xml = etree.parse( f )
print( xml )
root = xml.getroot()
print( root )
这样,你就可以看到发生了什么。
【讨论】:
抱歉,xml 文件本身有问题,但我现在已修复。无论如何,我在 writer.writerow([x.text for x in a]) 行遇到另一个错误:I/O operation on a closed file 这是因为writerow
不在with open(outfile, 'w') as file_:
结构内——注意for
的缩进级别终止with
并关闭相关文件。以上是关于在 python 中使用 Argparse 将 xml 转换为 csv的主要内容,如果未能解决你的问题,请参考以下文章
在 python 中使用 Argparse 将 xml 转换为 csv