Email parser work on individual data; breaks when used in loops list comprehensions, then breaks on original data as well… then works with map
这里有一些奇怪的神秘行为。
编辑这个已经很长很纠结了,我已经编辑了10次了。TL/DR是在处理某些文本的过程中,我设法编写了一个函数:
处理列表中的单个字符串
当我试图用列表理解将它应用到整个列表时,会抛出各种错误
当我试图用循环将其应用于整个列表时,会引发类似的错误
在抛出这些错误之后,停止处理单个字符串,直到我重新运行函数定义并向其提供一些示例数据,然后它再次开始工作,最后
当我用map()将它应用到整个列表时,结果是有效的。
有一个保存为html的ipython笔记本显示了这里的混乱:http://paul-gowder.com/wtf.html---我在上面放了一个链接,可以跳过一些不相关的东西。我还做了一个[另一个]要点,只是有问题代码和一些示例数据,但由于这个问题似乎以某种方式抛出了一堆状态,我不能保证它可以从中复制:https://gist.github.com/paultopia/402891d05dd8c05995d2
结束TL/DR,开始混乱
我正在对旧的安然数据集进行一些玩具文本挖掘,在加载了nltk stopwords等之后,我有以下一组功能来清理准备将其转换为文档术语矩阵的电子邮件。下面使用了python 2.7中的电子邮件库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | def parseEmail(document): # strip unnecessary headers, header text, etc. theMessage = email.message_from_string(document) tofield = theMessage['to'] fromfield = theMessage['from'] subjectfield = theMessage['subject'] bodyfield = theMessage.get_payload() wholeMsgList = [tofield, fromfield, subjectfield, bodyfield] # get rid of any fields that don't exist in the email cleanMsgList = [x for x in wholeMsgList if x is not None] # now return a string with all that stuff run together return ' '.join(cleanMsgList) def lettersOnly(document): return re.sub("[^a-zA-Z]","", document) def wordBag(document): return lettersOnly(parseEmail(document)).lower().split() def cleanDoc(document): dasbag = wordBag(document) # get rid of"enron" for obvious reasons, also the .com bagB = [word for word in dasbag if not word in ['enron','com']] unstemmed =[word for word in bagB if not word in stopwords.words("english")] return [stemmer.stem(word) for word in unstemmed] print enronEmails[0][1] print cleanDoc(enronEmails[0][1]) |
在用Unicode字符串表示的电子邮件上运行这个命令的第一个(t减去半小时)产生了预期的结果:
然后在T-10,我添加了几行代码(由于删除和丢失,不幸的是……但见下文),其中包含一些列表理解,以便从Enrolemail中提取消息,对它们运行清除功能,然后将它们重新连接到字符串中,以便通过sklearn方便地转换为文档术语矩阵。但是函数开始抛出错误。所以我戴上了调试帽…
首先,我尝试重新运行原始定义和测试单元。但当我重新运行该单元格时,我的电子邮件解析函数突然开始在消息中抛出错误"from_string method:
1 | AttributeError: 'list' object has no attribute 'message_from_string' |
号
所以这很奇怪。这是完全相同的函数,对完全相同的数据调用:
所以检查了以确保我没有改变数据。
但情节越来越复杂
然后我去了一个"制造要点"来创建一个完全可复制的例子来发布这个问题。我从工作部分开始。要点:https://gist.github.com/paultopia/c8c3e066c39336e5f3c2。
为了确保它能正常工作,首先我把它放在一个普通的.py文件中,然后从命令行运行它。它起作用了。
然后我把它和其他东西一起放在ipython笔记本底部的一个手机里。这也起作用了。
然后我在
但是那时然后我又回到里面,用清单上的理解之类的东西再试了一次。这一次,我更仔细地跟踪发生的事情。添加以下单元格:
1。
1 2 3 | def atLeastThreeString(cleandoc): return ' '.join([w for w in cleandoc if len(w)>2]) print atLeastThreeString(cleanDoc(enronEmails[0][1])) |
这可以工作,并产生预期的输出:单词超过2个字母的字符串。但接下来:2。
1 2 | justEmails = [email[1] for email in enronEmails] bigEmailsList = [atLeastThreeString(cleanDoc(email)) for email in justEmails] |
。
突然间,它开始抛出一个全新的错误,在回溯中的相同位置:
1 | AttributeError: 'unicode' object has no attribute 'message_from_string' |
这很有趣,因为我一分钟前给它传递了unicode字符串,它做得很好。而且,只是为了加强情节,然后返回并重新运行
这让我发疯了。如何可能创建一个新列表,然后尝试在该列表上运行函数A,不仅会在新列表上引发错误,还会导致函数A在以前处理的数据上引发错误?我知道我不会改变原来的名单…
如果有人想看到完整的代码和回溯,我已经在这里以HTML格式发布了整个笔记本:http://paul-gowder.com/wtf.html相关部分从下面的2/3开始,在24-5号单元格,在那里工作,然后26号单元格,wh
我认为问题在于这些阶段:
1 2 | justEmails = [email[1] for email in enronEmails] bigEmailsList = [atLeastThreeString(cleanDoc(email)) for email in justEmails] |
在python 2中,虚拟变量email会泄漏到名称空间中,因此您要重写email模块的名称,然后尝试在python字符串上从该模块调用一个方法。我在python 2中没有