我正在编写一些应该解析CSV文件的python代码。计算特定行的平均值,然后根据CSV文件中一行的值向收件人发送电子邮件。我的代码如下,我现在删除了发送代码的电子邮件,并将其替换为print语句:
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。似乎我不能在字典上调用列表理解然后迭代同一个字典。知道我做错了什么以及如何解决它?
答案 0 :(得分:6)
csv
模块返回的阅读器对象表现为生成器,它们只能迭代一次。如果您想要一个可以重复迭代的真实列表,则必须明确创建:
ldap_data = list(csv.DictReader(ldap_file))
答案 1 :(得分: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:
答案 2 :(得分:1)
那是因为ldap_data
是一个只支持迭代器协议的读者对象。这意味着您只能迭代一次,这是您在创建scores
列表时所做的。
你必须把它放在一个集合中,或者,如果文件太大,在循环之前再读一遍。
答案 3 :(得分:0)
ldap数据的类型是什么?
我感觉它是一个迭代器,而不是一个列表,所以如果你遍历它一次(例如在列表解析中),下次你尝试迭代它时会立即抛出“StopIteration”。
尝试在
后立即将其复制到列表中ldap_data = csv.DictReader(ldap_file)
ldap_data = list(ldap_data)