2012-01-09 23 views
2

我正在写一些应该解析CSV文件的Python代码。计算特定行的平均值,然后根据CSV文件中的一行值向收件人发送电子邮件。我的代码如下,我已删除了电子邮件的发送,现在的代码和一个print语句替换它:For循环字典不工作后执行列表理解

def main(): 
    #smtp_instance = smtplib.SMTP('localhost') 
    ldap_file = open('ldaps.csv','rU') 
    ldap_data=csv.DictReader(ldap_file) 
    scores = list(int(d['score']) for d in ldap_data) 

    average_score = sum(scores)/len(scores) 
    print average_score 

    for rows in ldap_data: 
    ldap = rows['ldap'] 
    fullname = rows['fullname'] 
    firstname = fullname.split(' ')[0] 
    location = rows['location'] 
    score = rows['score'] 
    if int(score) < average_score: 
     score_msg = 'below' 
    else: 
     score_msg = 'above' 

    print 'Hi ' + firstname + '\n'\ 
      'You got a ' + score + '% on your Final Exam.'\ 
      'The average score was ' + average_score + '.'\ 
      'This means that you scored ' + score_msg + ' average.' 

if __name__ == '__main__': 
    main() 

当我运行这个它打印AVERAGE_SCORE值。但代码从来没有得到for..loop。似乎我不能在dict上调用列表理解,然后在同一个dict上迭代。任何想法我做错了,我该如何解决它?

+0

尝试只打印'ldap_data'之前和之后的理解,如果你认为它是受到损坏。或者用'pdb'遍历它并检查相同的东西。 – Useless 2012-01-09 13:29:36

回答

6

读者对象由csv模块返回的模块表现为生成器,它们只能迭代一次。如果你想,你可以多次重复一个真正的列表,你必须明确地创建:

ldap_data = list(csv.DictReader(ldap_file)) 
+0

感谢这工作就像一个魅力 – jwesonga 2012-01-09 13:47:42

1

此行

scores = list(int(d['score']) for d in ldap_data) 

消耗在ldap_data的所有数据。 ldap_data是由文件ldap_file中的基础数据驱动的迭代器。在遍历ldap_data时,底层文件ldap_file被消耗。

因此ldap_data在到达for-loop时为空。解决此

for rows in ldap_data: 

一种方法是使ldap_data列表:

ldap_data = list(csv.DictReader(ldap_file)) 

解决这个另一种方式是告诉ldap_file再次从开始阅读:

scores = list(int(d['score']) for d in ldap_data) 
... 
ldap_file.seek(0) 
... 
for rows in ldap_data: 
1

这是因为ldap_data为读者对象,只支持迭代器协议。这意味着您只能迭代一次,您在创建scores列表时会执行该操作。

你必须把它放在一个集合中,或者如果文件太大,在循环之前再读一遍。

0

ldap数据的类型是什么?我有一种感觉它是一个迭代器,而不是一个列表,所以如果你迭代它一次(例如在列表理解中),下一次你尝试遍历它将立即抛出“StopIteration”。

尝试将其复制到一个列表后立即

ldap_data = csv.DictReader(ldap_file) 
ldap_data = list(ldap_data)