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='[email protected]', username='[email protected]', 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() 可以解决问题。但这不允许我添加主题行。
I have written a daemon of sorts to monitor files in a directory and send out an email whenever there is a change in any of the files. I used bb-freeze to compile it to a Windows .exe. I noticed after letting it run for a couple of days that it was taking more and more space in memory.
I used Heapy to monitor the memory usage in the .py file (not the compiled .exe) and found out that for each call to the function, the number of objects was increasing by 3 with a corresponding memory usage increase of 484 Bytes. It uses the smtplib module and I cannot understand where the leak is happening.
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='[email protected]', username='[email protected]', 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)
I just saw this code somewhere on the internet and copied it. It works but leaks memory.
Can someone help me find out where the memory leak is happening?? :(
EDIT: Seems like using msg.as_string() is what is causing the memory leak. Using a plain text such as msg="Blah" in place of msg.as_string() fixes the issue. But that does not allow me to add a subject line.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以访问 Valgrind 吗?这是查找内存泄漏的好工具。您还可以尝试使用 Python 调试器。
编辑:
抱歉,刚刚注意到你说你在 Windows 上,valgrind 不适用于:(。
无论如何,你可能想研究一下 Python for Windows 用于加密的任何库。在我的 Mac 上,你提供的脚本显示了一个内存围绕
mailServer.starttls()
调用的泄漏,罪魁祸首似乎是 libssl/libcrypto 周围的 python 包装器。抱歉,如果这根本没有帮助(非 Windows...)。Do you have access to Valgrind? That is a great tool for finding memory leaks. You could also try using the Python Debugger.
EDIT:
Sorry, just noticed you said you were on Windows, which valgrind is not available for :(.
Anyway, you might want to look into whatever library Python for Windows uses for crypto. On my Mac, the script you provided shows a memory leak around the
mailServer.starttls()
call, and the culprit looks to be the python wrapper around libssl/libcrypto. Sorry if this is no help at all (being non-windows...).1)您可以尝试使用简单的字符串文本作为消息执行相同的代码。
2)您可以删除对 ehlo 的调用,然后查看内存泄漏是否已修复。 (它们是不必要的)
1) You could try to do the same code with simple string text as message.
2) You could remove the calls to ehlo and see if the memory leak is fixed by this. (they are unnecessary)
我敢打赌你有一个参考周期。
编辑:我将您的代码稍微更改为:
Guppy 不适用于我拥有的 python 和 c++ 编译器版本,因此我无法测试该输出(也许它也不适合您?)。我可以告诉您的是,我观察了进程资源管理器中的垃圾收集输出和一些内存统计信息,发现该代码中没有重大差异或泄漏问题。关键更改:删除了对 SMTP.ehlo() 的调用(不必要),删除了默认函数参数(我怀疑这些参数可能会作为对象保留下来,只要函数在作用域内,就可以引用这些对象,这可能会以某种方式保留 SMTP周围的物体)。因此,您可能想先尝试一种,然后再尝试另一种,看看哪一种可以解决您的问题。
查看这篇文章获取帮助和一些工具。
I would bet that you have a reference cycle.
Edit: I altered your code slightly to:
Guppy does not work for the version of python and c++ compiler I have, so I couldn't test that output (maybe it doesn't work for you either?). What I can tell you is that I watched the garbage collection output and some memory statistics in process explorer and found no significant variance or issues with a leak in that code. Key changes: removed calls to SMTP.ehlo() (unnecessary), removed default function parameters (I suspected these might stay around as objects that could be referred to as long as long as the function was in scope, which might somehow keep the SMTP objects around). So you might want to try one then the other and see which fixes your problem.
Check out this post for assistance and some tools.