2016-02-11 3 views
5

Ich habe ein Python-Skript, das einige URLs kratzt. Ich habe eine Liste von URLs und für jede URL bekomme ich HTML und mache ein wenig Logik damit.Freigabe von Speicher in Python-Skript

Ich benutze Python 2.7.6 und Linux Mint 17 Cinnamon 64-Bit.

Problem ist, dass mein Hauptobjekt für Scraping, das ich für jede URL instanziiere, nie aus dem Speicher freigegeben wird, obwohl es keinen Verweis darauf gibt. Mit diesem Problem wächst und wächst mein Gedächtnis schnell (da mein Objekt manchmal sehr groß ist - bis zu 50MB).

Vereinfachen Code sieht etwa so aus:

def scrape_url(url): 
    """ 
    Simple helper method for scraping url 
    :param url: url for scraping 
    :return: some result 
    """ 
    scraper = Scraper(url) # instance main Scrape object 
    result = scraper.scrape() # scrape it 

    return result 

## SCRIPT STARTS HERE 
urls = get_urls() # fetch some list of urls 

for url in urls: 
    print 'MEMORY USAGE BEFORE SCRAPE: %s (kb)' % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 
    result = scrape_url(url) # call helper method for scraping 
    print 'MEMORY USAGE AFTER SCRAPE: %s (kb)' % resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 
    print '-' * 50 

Meine Ausgabe ist so etwas wie diese:

MEMORY USAGE BEFORE SCRAPE: 75732 (kb) 
MEMORY USAGE AFTER SCRAPE: 137392 (kb) 
-------------------------------------------------- 
MEMORY USAGE BEFORE SCRAPE: 137392 (kb) 
MEMORY USAGE AFTER SCRAPE: 206748 (kb) 
-------------------------------------------------- 
MEMORY USAGE BEFORE SCRAPE: 206748 (kb) 
MEMORY USAGE AFTER SCRAPE: 284348 (kb) 
-------------------------------------------------- 

Scrape Objekt ist groß und es ist nicht aus dem Speicher freigegeben. Ich habe versucht:

scraper = None 

del scraper 

oder sogar gc rufen mit dem Objekt zu sammeln:

gc.collect() 

aber nichts half.

Wenn ich Reihe von Verweisen auf Schaber Objekt drucken mit:

print sys.getrefcount(scraper) 

bekomme ich die ich denke, bedeutet, dass es keine anderen Verweise Objekt und sollte von gc gereinigt werden.

Scraper-Objekt hat viele Unterobjekte. Ist es möglich, dass einige der Sub-Objekt-Referenzen irgendwo liegen bleiben und aus diesem Grund kann gc das Haupt-Scaper-Objekt nicht freigeben oder gibt es einen anderen Grund, warum Python keinen Speicher freigibt?

fand ich einige Thema in Bezug auf diese in SO und einige der Antworten, wo sie diese Erinnerung sprechen kann nicht freigegeben werden, wenn Sie untergeordnete Prozesse/Tötung laichen, die wirklich seltsam klingt (LINK)

Danke, Ivan

+1

"Scraper-Objekt hat viele Unterobjekte ... gibt Speicher nicht frei?" das wäre der einzig plausible Grund. scrape url stellte eine Verbindung auf einem Port her, nehme ich an? Wahrscheinlich hält diese Verbindung die stehende Referenz. – user2255757

+0

Sind Sie sicher, dass das Ergebnis nicht mit Scrapper verbunden ist? – Jerzyk

Antwort

1

Sie verwenden einen Iterator, der immer im Speicher sein muss. Schreiben Sie Ihre Schleife neu, um den Generator zu verwenden und langsam zu kratzen. Etwas in der Art von:

def gen(): 
     for i in xrange(0, len(urls)): 
      yield urls[i] 
+1

oder Generator Ausdruck mit gen = (URL für URL in URLs) – Marcin