2015-11-04 28 views
0

我想为我的编程类解决问题。我收到一个包含电子邮件和特殊文件的文件夹。特殊文件始终以“!”开头。我应该在Corpus类中添加一个方法emails()。该方法应该是一个生成器。这是其使用的例子:通过生成器迭代时发生IndexError

corpus = Corpus('/path/to/directory/with/emails') 
count = 0 
# Go through all emails and print the filename and the message body 
for fname, body in corpus.emails(): 
    print(fname) 
    print(body) 
    print('-------------------------') 
    count += 1 
print('Finished: ', count, 'files processed.') 

这是类和我写的方法:

class Corpus: 
    def __init__(self, path_to_mails_directory): 
     self.path_to_mails_directory = path_to_mails_directory 

    def emails(self): 
    iterator = 0 
    mail_body = None 
    mails_folder = os.listdir(self.path_to_mails_directory) 
    lenght = len(mails_folder) 
    while iterator <= lenght: 
     if not mails_folder[iterator].startswith("!"): 
      with open(self.path_to_mails_directory+"/"+mails_folder[iterator]) as an_e_mail: 
       mail_body = an_e_mail.read() 
      yield mails_folder[iterator], mail_body 
     iterator += 1 

,我试图运行示例代码是这样的:

if __name__ == "__main__": 
    my_corpus = Corpus("data/1") 
    my_gen = my_corpus.emails() 
    count = 0 
    for fname, body in my_gen: 
     print(fname) 
     print(body) 
     print("------------------------------") 
     count += 1 
    print("finished: " + str(count)) 

Python按预期打印了一堆邮件(该文件夹包含大约一千个文件),然后执行:

Traceback (most recent call last): 
    File "C:/Users/tvavr/PycharmProjects/spamfilter/corpus.py", line 26, in <module> 
    for fname, body in my_gen: 
    File "C:/Users/tvavr/PycharmProjects/spamfilter/corpus.py", line 15, in emails 
    if not mails_folder[iterator].startswith("!"): 
IndexError: list index out of range 

我不知道问题是什么,并希望得到任何帮助。 Thx

编辑:我更新了一些基于您的建议的代码。

+0

在什么情况下你期望'while 1'循环退出? –

+0

'os.listdir'返回文件列表(例如'[“file1.txt”,“file2.txt”]'等等),您将它视为2维数组。从你的行删除'[0]'。 – CristiFati

+0

@CristFati - 这是真的,但不会解决用户的异常。 'mails_folder [iterator] [0]'将是文件名的第一个字母,并且检查该字母是否为'startswith(“!”)'是有效的。与仅仅检查文件名本身相比,非常详细,如果字符串可能是空字符串(我不认为它可以在'os.listdir的结果中)不安全,但这不是核心问题。 –

回答

0

一个好办法做到这将是如下:基于

def emails(self): 
    mail_body = None 
    mails_folder = os.listdir(self.path_to_mails_directory) 
    for mail in mails_folder: 
     if mail.startswith("!"): 
      pass 
     else: 
      with open(self.path_to_mails_directory+"/"+mail) as an_e_mail: 
       mail_body = an_e_mail.read() 
      yield mail, mail_body 

指数迭代不被认为是Python的。你应该更喜欢“邮件在mails_folder:”语法。

+0

非常感谢,它解决了这个问题。 –

+0

但我想知道:基于索引的迭代有什么问题? –

+0

安全;你永远不会得到一个索引错误。可读性; python程序员不习惯看到基于索引的循环。我也会想象Python对'for x in y:'风格的循环进行了优化。 – Prayag