簡體   English   中英

Python smtplib模塊泄漏內存

[英]Python smtplib module leaks memory

我編寫了各種守護程序來監視目錄中的文件,並在任何文件發生更改時發送電子郵件。 我使用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()可解決此問題。 但這不允許我添加主題行。

我敢打賭,您有一個參考周期。

編輯:我將您的代碼稍作更改為:

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周圍的物體)。 因此,您可能要嘗試一個然后另一個,然后看看哪個可以解決您的問題。

查看這篇文章以獲得幫助和一些工具。

您可以使用Valgrind嗎? 那是查找內存泄漏的好工具。 您也可以嘗試使用Python Debugger

編輯:

抱歉,剛剛注意到您說您在Windows上,該valgrind不適用於:(。

無論如何,您可能想研究Python for Windows用於加密的任何庫。 在我的Mac上,您提供的腳本顯示了mailServer.starttls()調用周圍的內存泄漏,而罪魁禍首似乎是libssl / libcrypto周圍的python包裝器。 抱歉,這根本沒有幫助(非Windows ...)。

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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM