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

Posted

技术标签:

【中文标题】使用 Argparse 在 Python 中创建文件转换器【英文标题】:Using Argparse to create file converter in Python 【发布时间】:2013-06-06 07:29:41 【问题描述】:

我必须使用命令提示符和 python 来接收 csv 文件形式的输入,然后读取它并将其转换为与 csv 文件同名的 xml 文件,但文件扩展名为 .xml 或用户可以使用 -o --output 可选命令行参数设置输出文件名和路径。好吧,我已经在谷歌上搜索了好几天,到目前为止,我的程序允许我输入命令行参数,我可以将 csv 转换为 xml 文件,但它不会使用与 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()
        if args.verbose: 
            print ('Verbose Selected')
        if args.toxml:
            if args.verbose:
               print ('Convert to XML Selected')
            generate_xml(reader)
        if args.readcsv:
            if args.verbose:
                print ('Reading CSV file')
            read_csv()
        if not (args.toxml or args.readcsv):
            parser.error('No action requested')
        return 1

    def read_csv():
        with open ('1250_12.csv', 'r') as data:
            return list(csv.reader(data))

    def generate_xml(reader):
        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(open('hole.xml','w'))
    if (__name__ == "__main__"):

sys.exit(main(sys.argv))

对于 generate_xml() 函数,您可以忽略它,因为它接受以某种方式格式化的 csv 文件,因此您可能不理解它,但我认为问题在于 tree.write() 因为该部分生成 xml 文件一个写在代码本身中的名称,而不是命令提示符下的参数。

【问题讨论】:

您的问题是什么:写入 XML 或写入具有给定路径/名称的文件?从你的问题看不清楚。 我无法将 csv 文件转换为与 csv 文件相同但扩展名为 .xml 的 xml 文件,并且我无法将 csv 文件转换为用户设置名称的 xml 文件新的 xml 文件。 该部分将 csv 文件转换为 xml 文件,但名称“hole.xml”写在代码中,这不是我想要的。我需要一些方法来使用命令提示符获取名称并将其设置为要使用从读取 csv 文件获得的数据生成的 xml 文件的名称 @Andy 你可以通过点击旁边的复选标记来接受答案:) 【参考方案1】:

您需要将文件参数传递给 generate_xml()。您似乎在 args.outputfile 中有输出文件。

generate_xml(reader, args.outputfile)

...
def generate_xml(reader, outfile):
    ...
    tree.write(outfile)

您可能还应该使用args.inputfile

reader = read_csv(args.inputfile)
...
def read_csv(inputfile):
    return list(csv.reader(inputfile))

这一行没有做任何有用的事情,它处理 .csv 文件,但对结果没有做任何事情:

read_csv()

【讨论】:

感谢您的帮助,但在我在命令提示符下运行后,出现错误:强制转换为 unicode:需要字符串或缓冲区,找到文件 对,我现在看到 args.inputfile 和 args.outputfile 已经是 File 类型的对象了。我会更新我的答案。 你如何调用你的脚本? argparse.py -i 1250_12.csv -x 其中 argparse.py 是名称,i- 是输入函数,1250_12.csv 是 csv 文件名,-x 是将 csv 转换为xml 好的,你需要添加一个-o output.xml【参考方案2】:

以下代码改编自FB36 在 code.activestate.com 上的收件人

它会满足您的需求,而且您不必担心 csv 文件中的标题,尽管 csv 文件中应该只有一个标题(第一行)。如果您想进行批量转换,请查看this page 的底部。

'''Convert csv to xml file

csv2xml.py takes two arguments:  
 1. csvFile: name of the csv file (may need to specify path to file)
 2. xmlFile: name of the desired xml file (path to destination can be specified)

If only the csv file is provided, its name is used for the xml file. 

Command line usage: 
 example1: python csv2xml.py 'fileName.csv' 'desiredName.xml'
 example2: python csv2xml.py '/Documents/fileName.csv' '/NewFolder/desiredName.xml'
 example3: python csv2xml.py 'fileName.csv'

This code has been adapted from: http://code.activestate.com/recipes/577423/
'''

import csv

def converter(csvFile, xmlFile):
    csvData = csv.reader(open(csvFile))

    xmlData = open(xmlFile, 'w')
    xmlData.write('<?xml version="1.0"?>' + "\n")

    # there must be only one top-level tag
    xmlData.write('<csv_data>' + "\n")

    rowNum = 0
    for row in csvData:
        if rowNum == 0:
            tags = row
            # replace spaces w/ underscores in tag names
            for i in range(len(tags)):
                tags[i] = tags[i].replace(' ', '_')
        else: 
            xmlData.write('<row>' + "\n")
            for i in range(len(tags)):
                xmlData.write('    ' + '<' + tags[i] + '>' \
                              + row[i] + '</' + tags[i] + '>' + "\n")
            xmlData.write('</row>' + "\n")

        rowNum +=1

    xmlData.write('</csv_data>' + "\n")
    xmlData.close()

## for using csv2xml.py from the command line
if __name__ == '__main__':
    import sys

    if len(sys.argv)==2:
        import os
        csvFile = sys.argv[1]
        xmlFile = os.path.splitext(csvFile)[0] + '.xml'
        converter(csvFile,xmlFile)
    elif len(sys.argv)==3:
        csvFile = sys.argv[1]
        xmlFile = sys.argv[2]   
        converter(csvFile,xmlFile)
    else:
        print __doc__

【讨论】:

以上是关于使用 Argparse 在 Python 中创建文件转换器的主要内容,如果未能解决你的问题,请参考以下文章

python 3 argparse调用一个函数

在 python 中使用 argparse 来解析整个 JSON

python标准库之argparse

Python:argparse 帮助文本的分页?

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

Python模块之argparse