Python - Потоковая программа, кажется, имеет утечку памяти? - PullRequest
0 голосов
/ 19 августа 2010

Я пишу программу на 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

Спасибо!

1 Ответ

0 голосов
/ 19 августа 2010

Вы пытаетесь открыть файл конфигурации для каждого потока, который занимает некоторое количество памяти.
Сколько URL вы проверяете?
Что такое реализация ConfigParser.
Вы уверены, что каждый поток присоединяется?
Закончены ли пакетные программы до следующего запланированного запуска?

...