Python 电子邮件解析器处理单个数据;在循环列表理解中使用时中断,然后在原始数据上也中断。。。然后使用map
这里有一些奇怪的神秘行为 编辑这已经变得很长很纠结了,我已经编辑了10次了。TL/DR是指在处理某些文本的过程中,我成功地编写了一个函数:Python 电子邮件解析器处理单个数据;在循环列表理解中使用时中断,然后在原始数据上也中断。。。然后使用map,python,loops,dictionary,list-comprehension,ipython-notebook,Python,Loops,Dictionary,List Comprehension,Ipython Notebook,这里有一些奇怪的神秘行为 编辑这已经变得很长很纠结了,我已经编辑了10次了。TL/DR是指在处理某些文本的过程中,我成功地编写了一个函数: 处理列表中的单个字符串 当我试图使用列表理解将其应用于整个列表时,抛出各种错误 当我尝试使用循环将其应用于整个列表时,会引发类似的错误 抛出这些错误后,停止处理单个字符串,直到我重新运行函数定义并向其提供一些示例数据,然后它再次开始工作,最后 当我使用map()将其应用于整个列表时,结果证明是有效的 有一个ipython笔记本保存为html,在这里显示了
- 处理列表中的单个字符串
- 当我试图使用列表理解将其应用于整个列表时,抛出各种错误
- 当我尝试使用循环将其应用于整个列表时,会引发类似的错误
- 抛出这些错误后,停止处理单个字符串,直到我重新运行函数定义并向其提供一些示例数据,然后它再次开始工作,最后
- 当我使用map()将其应用于整个列表时,结果证明是有效的
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])
首先(T减去半小时)在一封表示为unicode字符串的电子邮件上运行此命令,产生了预期的结果:print cleanDoc(enronEmails[0][1])
生成了一个词干单词列表。需要说明的是,enronEmails的底层数据是[label,message]列表的列表,其中label是整数0或1,message是unicode字符串。(在python 2.7中)
然后在t-10,我添加了几行代码(不幸的是,由于删除和丢失,但请参见下文),其中包含一些列表理解,以便从enronEmails中提取消息,在它们上运行我的清理功能,然后将它们连接回字符串,以便通过sklearn方便地转换为文档术语矩阵。但是函数开始抛出错误。所以我戴上了调试帽
首先,我尝试重新运行原始定义和测试单元。但当我重新运行该单元格时,我的电子邮件解析功能突然开始在消息\u from\u string方法中抛出错误:
AttributeError: 'list' object has no attribute 'message_from_string'
所以这很奇怪。这是完全相同的函数,对完全相同的数据调用:cleanDoc(enronEmails[0][1])
。函数在相同的数据上工作,我没有改变它
所以我检查了一下以确保我没有改变数据enronEmails[0][1]
仍然是一个字符串。不是名单。我不知道为什么traceback认为我正在将列表传递给cleanDoc()。我没有
但是情节变厚了
然后我去了一家公司,做了一个要点,创建了一个完全可复制的例子,以便发布这个问题。我从工作部分开始。要点:
为了确保它正常工作,首先我将它放在一个普通的.py文件中,并从命令行运行它。成功了
然后我把它和其他东西一起放在我的ipython笔记本底部的一个单元格里。这也奏效了
然后我在enronEmails[0][1]上尝试了parseEmail函数。这又起作用了。然后我一路返回到五分钟前抛出错误的原始单元格,并重新运行它(包括从sklearn导入的内容,以及所有函数的原始定义)而且它非常有效。
但是
然后我又回去,用列表的理解力之类的东西再试了一次。这一次,我更仔细地跟踪了正在发生的事情。添加以下单元格:
一,
这可以工作,并产生预期的输出:一个单词超过2个字母的字符串。但是:
二,
突然,它开始抛出一个全新的错误,在回溯中的同一个位置:
AttributeError: 'unicode' object has no attribute 'message_from_string'
这非常有趣,因为我一分钟前在传递unicode字符串,它做得很好。而且,为了使绘图更厚,返回并重新运行cleanDoc(enronEmails[0][1])
会抛出相同的错误
这快把我逼疯了。创建一个新列表,然后尝试在该列表上运行函数a,这怎么可能不仅会在新列表上引发错误,还会导致函数a在以前处理的数据上引发错误?我知道我没有改变原来的名单
如果有人想看到完整的代码和回溯,我已经在这里以html的形式发布了整个笔记本:相关的部分从下面的2/3开始,在24-5号单元格开始工作,然后是26号单元格,在那里爆炸
帮助
另一个编辑:我在上面链接的html笔记本底部添加了一些调试工作。正如您所看到的,我已经将问题追溯到循环行为,无论是以列表理解形式隐式完成还是显式完成。我的函数只对电子邮件列表中的单个项目起作用,但当我尝试循环该列表时,每个项目都会失败,但使用map()时除外????世界疯了吗?我认为问题在于这些观点:
justEmails = [email[1] for email in enronEmails]
bigEmailsList = [atLeastThreeString(cleanDoc(email)) for email in justEmails]
在Python2中,伪变量email泄漏到名称空间中,因此您将覆盖电子邮件模块的名称,然后尝试在python字符串上从该模块调用方法。我在Python2中没有
ntlk
,所以我无法测试它,但我想这一定是它。ooh!这也许可以很好地解释这一点。我要去测试一下,但是,在搜索之后,只是为了添加到
AttributeError: 'unicode' object has no attribute 'message_from_string'
justEmails = [email[1] for email in enronEmails]
bigEmailsList = [atLeastThreeString(cleanDoc(email)) for email in justEmails]