Модуль Python smtplib утечки памяти - PullRequest
1 голос
/ 23 марта 2011

Я написал своего рода демон для мониторинга файлов в каталоге и отправки электронного письма всякий раз, когда происходит изменение в любом из файлов.Я использовал 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 ]

1 голос
/ 23 марта 2011

Могу поспорить, что у вас есть справочный цикл.

Редактировать: я немного изменил ваш код так:

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)

Гуппи не работает для версии Python и компилятора C ++ Iесть, поэтому я не могу проверить этот вывод (может быть, он не работает для вас тоже?).Что я могу вам сказать, так это то, что я наблюдал за выводом сборки мусора и статистикой памяти в Process Explorer и не обнаружил значительных отклонений или проблем с утечкой в ​​этом коде.Основные изменения: удалены вызовы SMTP.ehlo () (не нужны), удалены параметры функций по умолчанию (я подозревал, что они могут оставаться объектами, на которые можно ссылаться, пока функция находится в области видимости, которая может каким-то образом сохранять SMTPобъекты вокруг).Так что вы можете попробовать один, а потом другой и посмотреть, что решает вашу проблему.

Проверьте этот пост за помощью и некоторыми инструментами.

0 голосов
/ 23 марта 2011

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()
0 голосов
/ 23 марта 2011

У вас есть доступ к Valgrind ? Это отличный инструмент для поиска утечек памяти. Вы также можете попробовать использовать Python Debugger .

EDIT:

Извините, только что заметил, что вы говорили, что вы работали в Windows, для которой valgrind недоступен: (.

В любом случае, вы можете захотеть взглянуть на любую библиотеку, которую Python для Windows использует для шифрования. На моем Mac предоставленный вами скрипт показывает утечку памяти вокруг вызова mailServer.starttls(), и виновник выглядит как оболочка python вокруг libssl / libcrypto. Извините, если это вообще не поможет (будучи не Windows ...).

...