Python newb:什么阻止了这个功能的打印?

时间:2014-06-18 16:27:44

标签: python xml csv

背景

我没有使用python,但我想用它来为我生成一些重复的XML。现在,我只想解析CSV,然后将这些值传递给XML节。

有一个问题:在编写XML之前,我需要重写一些CSV。我有一些if语句来处理这个问题,我决定通过将它移到一个单独的函数来减少混乱。

这是我的问题出现的地方。当我返回重写的csvDict实例时,我的writeTypes函数似乎按预期工作但,我无法再打印值。

显然我错过了一些东西,可能很简单 - 但是什么?脚本以下评论。

脚本

import csv

def parseCSV(vals):

    # read the csv

    dictReader = csv.DictReader(open(vals, 'rb'), fieldnames=['name', 'type', 'nullable', 'default', 'description', '#'], delimiter=',', quotechar='"')

    # some repetitive xml; I will finish this portion later...

    stanza = '''
    <var name="{0}" precision="1" scale="None" type="{1}">
        <label>{2}</label>
        <definition><![CDATA[@{3}({4})]]></definition>
    </var>'''

    # a function that simply writes new values to dictionary entries 

    writeTypes(dictReader)

    # I'm confused here - nothing is printed to the console. 
    # If i comment my 'writeTypes function, prints as expected

    for i in dictReader:
        print i
        print i['type']


# function to rewrite 'types' key in dictionary set
def writeTypes(d):

    for i in d:
        if i['type'] == 'text':
            i['type'] = 't'
        elif i['type'] == 'boolean':
            i['type'] = 'l'
        elif i['type'] == 'double precision':
            i['type'] = 'd'
        elif i['type'] == 'integer':
            i['type'] = 'i'
        else:
            i['type'] = i['type']

         # unsurprisingly, this function does seem to print the correct values    
        print i

    # it seems as though there's something wrong with this return statement...
    return d

示例CSV

(公共数据来自.gov网站)

Name,Type,Nullable,Default,Description,#
control,text,true,,,1,false
flagship,boolean,true,,,1,false
groupid,text,true,,,1,false
hbcu,text,true,,,1,false
hsi,text,true,,,1,false
iclevel,text,true,,,1,false
landgrnt,text,true,,,1,false
matched_n_00_10_11,boolean,true,,,1,false
matched_n_05_10_6,boolean,true,,,1,false
matched_n_87_10_24,boolean,true,,,1,false
name,text,true,,,1,false
name_short,text,true,,,1,false
school,text,true,,,1,false
sector,text,true,,,1,false
sector_revised,text,true,,,1,false
top_50,boolean,true,,,1,false
virginia,boolean,true,,,1,false

2 个答案:

答案 0 :(得分:3)

dictReader是一个迭代器,一旦通过CSV文件读取它就会耗尽:进一步的迭代将不会做任何事情。

解决此问题的方法是在writeTypes中创建一个新的dicts列表,以便您在那里而不是在原始值中分配值。然后,您可以返回该列表,并在主函数中迭代该列表。

答案 1 :(得分:2)

@Jefftopia,问题是你第一次使用dictReader作为迭代器&#34;消耗&#34;整个文件,以便在您尝试第二次迭代时无需阅读。

当你这样做时......

# a function that simply writes new values to dictionary entries 

writeTypes(dictReader)

... writeTypes函数通过dictReader遍历CSV文件的行:

def writeTypes(d):
    for i in d:
        ...

然后您从该功能返回并尝试再次遍历dictReader 。问题是dictReader现在没有数据可以从底层文件读取,因为它已经完成了整个事情!

# I'm confused here - nothing is printed to the console. 
# If i comment my 'writeTypes function, prints as expected

for i in dictReader:
    print i
    print i['type']

当你在Python中使用file对象或大多数类似对象作为迭代器时,迭代器&#34;消耗&#34;文件。作为一般规则,无法可靠地读取类似文件的对象,然后再回到开头再次读取它(考虑网络套接字的情况,可能只传输一次数据。)

在这种特殊情况下,可以在第二次传递数据之前再次重新打开文件。 (还有更多的kludge-y解决方案,但我不会表现出来。)

# reopen the file in order to read through it a second time
dictReader = csv.DictReader(open(vals, 'rb'), fieldnames=['name', 'type', 'nullable', 'default', 'description', '#'], delimiter=',', quotechar='"')
for i in dictReader:
    print i
    print i['type']

多次传递文件处理有时可以大大简化这样的代码,尽管它也会损害大型文件的性能。在这种特殊情况下,一次性完成所有事情都很简单;您可以稍微重写代码,以便在迭代行时收集type字段。