Я пишу программу на python, которая, кажется, утечка памяти.
Программа принимает список URL-адресов и проверяет, что их код состояния равен 200. Если код состояния не равен 200, сценарий предупредит меня по электронной почте. Скрипт имеет многопоточность, поэтому URL можно проверять параллельно друг другу.
Я установил программу на одну из задач расписания нашего сервера, которая выполняется каждые 5 минут. С тех пор физическая память сервера была полностью использована. Сервер работает под управлением Windows Server 2008 и Python версии 2.6.
Где утечка памяти ??
Следующий код вызывает многопоточный класс UrlChecker.py (также включенный ниже):
from ConfigParser import ConfigParser
import re
from UrlChecker import UrlCheckerThread
from Logger import Logger
from classes.EmailAlert import EmailAlert
... {More Code is here} ...
urls = cfg.items('urls')
defaulttimeout = int(cfg.get('timeout', 'default', 0))
threadList = []
for name, url in urls:
m = re.search("\([0-9]*\)", name)
s = m.start() + 1
e = m.end() - 1
name = name[s:e]
checker = UrlCheckerThread(url, name)
threadList.append(checker)
checker.start()
for threads in threadList:
threads.join()
for x in threadList:
status = x.status
url = x.url
name = x.name
runtime = x.runtime
"""
If there is an error, put information in a dict for furher
processing.
"""
if(status != None and status != 200 or runtime >= defaulttimeout):
self.logDict[name]= (name, url, status, runtime)
UrlChecker.py
import socket
from threading import Thread, Lock
from urllib2 import Request, urlopen
from ConfigParser import ConfigParser
from TimeoutController import TimeoutController
from classes.StopWatch import StopWatch
class UrlCheckerThread(Thread):
lock = Lock()
threadId = 0
def __init__(self, url, name):
Thread.__init__(self)
self.url = url
self.name = name
self.cfg = ConfigParser()
self.cfg.read('c:\Websites\ServerManager\V100\webroot\Admin\SiteMonitor\config.cfg')
self.thisId = UrlCheckerThread.threadId
self.extendedTimeout = int(self.cfg.get('timeout', 'extended', 0))
self.tc = TimeoutController()
self.tc.setTimeout(self.extendedTimeout)
UrlCheckerThread.threadId += 1
def run(self):
"""
getHeader uses urlopen to check wether an website is online or not
"""
self.sw = StopWatch()
self.sw.start()
self.checker = UrlChecker()
UrlCheckerThread.lock.acquire()
self.status = self.checker.getStatus(self.url)
self.sw.stop()
self.runtime = self.sw.time()
"""
if(isinstance(self.status, socket.timeout)):
self.tc.setTimeout(self.extendedTimeout)
self.status = self.checker.getStatus(self.url)
if(self.status == 200):
self.status = 'short time out'
self.tc.setTimeout(self.defaultTimeout)
"""
UrlCheckerThread.lock.release()
class UrlChecker:
def getStatus(self, url):
"""
getHeader uses urlopen to check wether an website is online or not
"""
request = Request(url, None)
try:
urlReq = urlopen(request)
"""
getcode() return the HTTP status header, which should be 200
in most cases.
"""
return urlReq.getcode()
except IOError, e:
if hasattr(e, 'reason'):
"""
e.reason returns an IOError object, which cannot be just
inserted in the database. The IOError object is basically
a 2-Tuple with an errornumber and an errorstring.
Since an errornumber is less readable then a string,
we use e.reason.strerror to just return IOError's string
"""
return e.reason.strerror
elif hasattr(e, 'code'):
"""
e.code is an int object, which is perfectly fine to insert in
the database. So no further modification needed.
"""
return e.code
Спасибо!