2011-03-23 44 views
1

我已經編寫了一個守護程序來監視目錄中的文件,並在任何文件發生更改時發送電子郵件。我使用bb-freeze將其編譯爲Windows .exe。讓我們在運行了幾天後注意到它在內存中佔用的空間越來越大。Python smtplib模塊泄漏內存

我用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()修復了這個問題。不允許我添加主題行

+1

你應該在這裏添加你的答案作爲答案並接受它,而不是編輯你的帖子。或者,如果其中一個答案在這裏最終準確地反映了答案,您應該接受它。 :) – sarnold 2011-03-24 04:55:08

回答

0

你有一個使用的Python Debugger

編輯查找內存泄漏一個偉大的工具,您也可以嘗試Valgrind訪問:?。

對不起,只是注意到你說你在Windows上,哪個valgrind不能用於:(。

無論如何,您可能希望查看Windows的Python用於加密的任何庫。在我的Mac上,您提供的腳本顯示圍繞mailServer.starttls()調用的內存泄漏,並且罪魁禍首看起來是圍繞libssl/libcrypto的python包裝。對不起,如果這沒有幫助(非窗戶...)。

1

我敢打賭,你有一個參考週期。

編輯:我改變你的代碼稍微:

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

def sendMail(subject, text): 
    gmailUser = '[email protected]' 
    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) 

孔雀魚沒有爲Python和C++編譯器,我的版本的工作,所以我不能測試輸出(也許這是行不通的你呢?)。我可以告訴你的是,我在進程瀏覽器中觀察了垃圾收集輸出和一些內存統計信息,發現該代碼中沒有明顯的差異或泄漏問題。關鍵更改:刪除了對SMTP.ehlo()(不必要的)的調用,刪除了默認的函數參數(我懷疑這些參數可能保留在對象中,只要函數在範圍內,這些對象可以保持SMTP周圍的物體)。所以你可能想嘗試一個,然後看看哪個修復了你的問題。

查看this post獲取幫助和一些工具。

0

1)你可以嘗試用簡單的字符串文本做消息來做同樣的代碼。
2)您可以刪除對ehlo的調用,並查看內存泄漏是否由此修復。 (他們是不必要的)

import smtplib 


def main() : 
    fromaddr = '[email protected]' 
    toaddrs = '[email protected]' 
    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()