在python中使用argparse将csv转换为xml

Posted

技术标签:

【中文标题】在python中使用argparse将csv转换为xml【英文标题】:Using argparse to convert csv to xml in python 【发布时间】:2013-06-08 17:52:21 【问题描述】:

一个非常快速的问题,基本上我的程序接受一个输入文件,它是一个 csv 文件,然后将其转换为一个 xml 文件。但是,xml 文件的名称可以由用户输入设置,或者如果用户未指定名称,则 xml 文件将与 csv 文件具有相同的名称,但扩展名为 .xml。我需要后者的帮助。到目前为止,当为输出文件命名时,我的程序可以工作,但是当用户不输入名称时,我不知道如何设置 xml 文件名。我知道如果用户没有设置名称,则 argparse.outputfile 为无,我可以编写一个简单的 if 语句进行检查,但我不知道如何将名称设置为与之后的 csv 文件名相同。这是我的代码:

import sys, argparse
import csv
import indent
from xml.etree.ElementTree import ElementTree, Element, SubElement, Comment, tostring

parser=argparse.ArgumentParser(description='Convert wordlist text files to various formats.', prog='Text Converter')
parser.add_argument('-v','--verbose',action='store_true',dest='verbose',help='Increases messages being printed to stdout')
parser.add_argument('-c','--csv',action='store_true',dest='readcsv',help='Reads CSV file and converts to XML file with same name')
parser.add_argument('-x','--xml',action='store_true',dest='toxml',help='Convert CSV to XML with different name')
parser.add_argument('-i','--inputfile',type=argparse.FileType('r'),dest='inputfile',help='Name of file to be imported',required=True)
parser.add_argument('-o','--outputfile',type=argparse.FileType('w'),dest='outputfile',help='Output file name')
args = parser.parse_args()

def main(argv):
    reader = read_csv(args.inputfile)
    if args.verbose: 
        print ('Verbose Selected')
    if args.toxml:
        if args.verbose:
            print ('Convert to XML Selected')
        generate_xml(reader, args.outputfile)
    if args.readcsv:
        if args.verbose:
            print ('Reading CSV file')
    if not (args.toxml or args.readcsv):
        parser.error('No action requested')
    return 1

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')
    head.set('total_holes', '238')

    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    
    indent.indent(root)
    tree.write(outfile)

if (__name__ == "__main__"):
    sys.exit(main(sys.argv))

【问题讨论】:

我认为如果您只是将输入文件设置为必需的位置参数,并将输出文件设置为默认为修改后的输入名称的可选位置参数:script INPUT [OUTPUT],您的代码会简单得多。 -c(如图所示)是一个空操作,仅在未指定 -x 时才需要避免解析器错误。 【参考方案1】:

将“import os”添加到文件顶部的导入列表中。然后,在解析之后,您可以检查并设置参数:

if args.outputfile is None:
    args.outputfile = os.path.splitext(args.inputfile)[0] + '.xml'

顺便说一句,参数默认为其长选项名称。当您想使用不同的名称时,您只需要“dest”关键字。因此,例如,“详细”可以是:

parser.add_argument('-v', '--verbose', action='store_true',
    help='Increases messages being printed to stdout')

编辑:这是使用输出文件处理和 chepner 建议对文件名使用位置参数进行重新设计的示例。

import os
import sys
import argparse
import csv
import indent
from xml.etree.ElementTree import ElementTree, Element, SubElement, Comment, tostring

def get_args(args):
    parser=argparse.ArgumentParser(description='Convert wordlist text files to various formats.', prog='Text Converter')
    parser.add_argument('-v','--verbose',action='store_true',dest='verbose',help='Increases messages being printed to stdout')
    parser.add_argument('-c','--csv',action='store_true',dest='readcsv',help='Reads CSV file and converts to XML file with same name')
    parser.add_argument('-x','--xml',action='store_true',dest='toxml',help='Convert CSV to XML with different name')
    #parser.add_argument('-i','--inputfile',type=str,help='Name of file to be imported',required=True)
    #parser.add_argument('-o','--outputfile',help='Output file name')
    parser.add_argument('inputfile',type=str,help='Name of file to be imported')
    parser.add_argument('outputfile',help='(optional) Output file name',nargs='?')
    args = parser.parse_args()
    if not (args.toxml or args.readcsv):
        parser.error('No action requested')
        return None
    if args.outputfile is None:
        args.outputfile = os.path.splitext(args.inputfile)[0] + '.xml'
    return args

def main(argv):
    args = get_args(argv[1:])
    if args is None:
        return 1
    inputfile = open(args.inputfile, 'r')
    outputfile = open(args.outputfile, 'w')
    reader = read_csv(inputfile)
    if args.verbose:
        print ('Verbose Selected')
    if args.toxml:
        if args.verbose:
            print ('Convert to XML Selected')
        generate_xml(reader, outputfile)
    if args.readcsv:
        if args.verbose:
            print ('Reading CSV file')
    return 1 # you probably want to return 0 on success

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')
    head.set('total_holes', '238')

    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
    indent.indent(root)
    tree.write(outfile)

if (__name__ == "__main__"):
    sys.exit(main(sys.argv))

【讨论】:

不,您可以更改变量或添加新变量。 @Andy,好的,为“import os”添加了评论。 是的,我也试过了,但我也收到:属性错误:文件对象没有属性“rfind” @Andy 你用的是哪个版本的python?哪一行出现错误? python 2.7 和 splitext 部分有关

以上是关于在python中使用argparse将csv转换为xml的主要内容,如果未能解决你的问题,请参考以下文章

使用 Argparse 的 Python 错误

在python中使用没有动作参数的Argparse

使用 Argparse 在 Python 中创建文件转换器

Python将字典转换为argparse

在 python 中使用 argparse 更改文件扩展名

如何使用 Python 中的 argparse 和 csv 库编写文件?