0

J'écris un programme python qui semble fuir la mémoire. Le programme saisit une liste d'URL et s'assure que son code d'état est 200. Si le code d'état n'est pas 200, le script m'avertira par email. Le script est enfilé afin que les URL puissent être vérifiées en parallèle les unes des autres.Python - programme fileté semble avoir une fuite de mémoire?

J'ai défini le programme sur l'une des tâches de planification de notre serveur qui s'exécute toutes les 5 minutes. Depuis lors, la mémoire physique du serveur a été entièrement consommée. Le serveur exécute Windows Server 2008 et Python version 2.6.

Où est la fuite de mémoire ??

Le code suivant appelle la classe filetée UrlChecker.py (Sont également inclus ci-dessous):

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 

Merci!

Répondre

0

Vous essayez d'ouvrir le fichier de configuration pour chaque thread, ce qui prend un peu de mémoire.
Combien d'URL vérifiez-vous?
Qu'est-ce que l'implémentation de ConfigParser.
Etes-vous sûr que chaque thread se joint?
Les programmes batch sont-ils terminés avant la prochaine exécution planifiée?

+0

Vous essayez d'ouvrir le fichier de configuration pour chaque thread, ce qui prend un peu de mémoire. Votre droit, mais est-ce que cette mémoire est libérée par la récupération automatique des ordures? Combien d'URL vérifiez-vous? Je suis actuellement en train de vérifier 19 URL. Qu'est-ce que l'implémentation de ConfigParser? Im utilisant l'analyseur intégré de Python. à partir de ConfigParser import ConfigParser Etes-vous sûr que chaque thread se joint? Non Je ne suis pas ... Dois-je terminer le fil après la fin du processus? Les programmes batch sont-ils terminés avant la prochaine exécution planifiée? Oui, le programme de tâches de planification Windows est configuré pour ne pas s'exécuter plusieurs fois à la fois. –