Python smtplib模块泄漏内存

时间:2011-03-23 17:33:47

标签: python smtplib

我编写了一个守护程序来监视目录中的文件,并在任何文件发生更改时发送电子邮件。我使用bb-freeze将其编译为Windows .exe。我注意到它让它运行了几天,它在内存中占用了越来越多的空间。

我使用Heapy来监视.py文件(而不是编译的.exe)中的内存使用情况,并发现每次调用该函数时,对象的数量都会增加3并带有相应的内存使用量增加484字节。它使用smtplib模块,我无法理解泄漏发生的位置。

from guppy import hpy
import time
import gc

import os
import smtplib
import mimetypes
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEAudio import MIMEAudio
from email.MIMEImage import MIMEImage
from email.Encoders import encode_base64

def sendMail(subject, text, to='blah@gmail.com', username='more.blah@gmail.com', password='blah', smtpServer='smtp.gmail.com', smtpPort=587):
   gmailUser = username
   gmailPass = password
   recipient = to

   msg = MIMEMultipart()
   msg['From'] = gmailUser
   msg['To'] = recipient
   msg['Subject'] = subject
   msg.attach(MIMEText(text))

   mailServer = smtplib.SMTP(smtpServer, smtpPort)
   mailServer.ehlo()
   mailServer.starttls()
   mailServer.ehlo()
   mailServer.login(gmailUser, gmailPass)
   mailServer.sendmail(gmailUser, recipient, msg.as_string())
   mailServer.quit()

   print('Sent email to "%s"' % recipient)

if __name__=='__main__':
   while True:
      sendMail("Function", "Blah!")
      gc.collect()
      print hpy().heap()
      time.sleep(10)

我刚刚在互联网上的某处看到了这段代码并将其复制了。它工作但泄漏记忆。 有人可以帮我找出内存泄漏发生的地方吗? :(

编辑:似乎使用msg.as_string()是导致内存泄漏的原因。使用诸如msg =“Blah”之类的纯文本代替msg.as_string()可以解决问题。但这不允许我添加主题。

3 个答案:

答案 0 :(得分:1)

我敢打赌你有一个参考周期。

编辑:我稍微修改了您的代码:

import time
import gc
import smtplib
import mimetypes
from email.MIMEText import MIMEText

def sendMail(subject, text):
   gmailUser = 'myemail@gmail.com'
   gmailPass = 'mypassword'
   recipient = gmailUser

   msg = MIMEMultipart()
   msg['From'] = gmailUser
   msg['To'] = recipient
   msg['Subject'] = subject
   msg.attach(MIMEText(text))

   mailServer = smtplib.SMTP('smtp.gmail.com', 587)
   mailServer.starttls()
   mailServer.login(gmailUser, gmailPass)
   mailServer.sendmail(gmailUser, recipient, msg.as_string())
   mailServer.quit()

   print('Sent email to "%s"' % recipient)

if __name__=='__main__':
   gc.set_debug(gc.DEBUG_LEAK)
   for item in range(1000):
      sendMail("Function", "Blah!")
      gc.collect()
      time.sleep(2)

Guppy不适用于我所拥有的python和c ++编译器版本,因此我无法测试该输出(也许它对你不起作用?)。我可以告诉你的是,我在进程资源管理器中查看了垃圾收集输出和一些内存统计信息,发现该代码中没有明显的差异或泄漏问题。密钥更改:删除了对SMTP.ehlo()的调用(不必要),删除了默认函数参数(我怀疑这些参数可能会作为对象保留,只要该函数在范围内,可能以某种方式保留SMTP周围的物体)。所以你可能想尝试另一个,看看哪个解决了你的问题。

查看this post以获取帮助和一些工具。

答案 1 :(得分:0)

您是否可以访问Valgrind?这是查找内存泄漏的好工具。您也可以尝试使用Python Debugger

编辑:

抱歉,刚刚注意到你说你在Windows上,valgrind不适用于:(。

无论如何,您可能想要查看Python for Windows用于加密的任何库。在我的Mac上,您提供的脚本显示mailServer.starttls()调用周围的内存泄漏,罪魁祸首看起来是围绕libssl / libcrypto的python包装器。对不起,如果这根本没有帮助(非windows ...)。

答案 2 :(得分:0)

1)您可以尝试使用简单的字符串文本作为消息执行相同的代码 2)您可以删除对ehlo的调用,并查看是否由此修复了内存泄漏。 (他们没必要)

import smtplib


def main() :
    fromaddr = 'ph111@gmail.com'
    toaddrs  = 'ph222@gmail.com'
    msg = 'my simple message'
    username = 'ph111'
    password = 'mypassword'
    server = smtplib.SMTP('smtp.gmail.com:587')
    server.starttls()
    server.login(username,password)
    server.sendmail(fromaddr, toaddrs, msg)
    server.quit()

if __name__ == '__main__':
    main()