2016-02-11 17 views
5

Ho uno script python che cancella alcuni URL. Ho una lista di URL e per ogni URL ottengo html e faccio un po 'di logica con esso.Rilascio di memoria in script python

Io uso Python 2.7.6 e Linux Mint 17 Cinnamon 64-bit.

Il problema è che il mio oggetto principale per lo scraping, quale istanza per ogni url, non viene mai rilasciato dalla memoria sebbene non ci sia riferimento ad esso. Con questo problema la mia memoria continua a crescere e crescere rapidamente (dal momento che il mio oggetto è talvolta molto grande - fino a 50 MB).

codice Semplificare simile a questa:

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 

La mia uscita è qualcosa di simile:

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) 
-------------------------------------------------- 

Raschiare oggetto è grande e non è rilasciato dalla memoria. ho provato:

scraper = None 

del scraper 

o anche chiamare GC per raccogliere oggetto con:

gc.collect() 

ma non serviva a niente.

Quando stampo numero di riferimenti a oggetto raschietto con:

print sys.getrefcount(scraper) 

ottengo che secondo me significa che non ci sono altri riferimenti a oggetto e deve essere pulita da GC.

L'oggetto raschietto ha molti sottooggetti. È possibile che alcuni di essi vengano lasciati da qualche parte e per questo motivo gc non può rilasciare l'oggetto Scaper principale o c'è qualche altra ragione per cui Python non rilascia la memoria?

ho trovato qualche argomento per quanto riguarda questo in SO e alcune delle risposte in cui stanno parlando che la memoria non può essere rilasciato a meno che non stanno deponendo le uova/uccidere i processi figli che suona davvero strano (LINK)

Grazie, Ivan

+1

"L'oggetto raschietto ha molti sottooggetti ... non rilascia memoria?" questa sarebbe l'unica ragione plausibile. urlo di scrap ha stabilito una connessione su una porta presumo? Probabilmente quella connessione mantiene il riferimento permanente. – user2255757

+0

sei sicuro che il risultato non è connesso con lo scrapper? – Jerzyk

risposta

1

Si sta utilizzando un iteratore, che deve essere sempre in memoria. Riscrivi il tuo loop per usare il generatore e pigramente. Qualcosa sulla falsariga di:

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

o espressione del generatore con gen = (url per url in urls) – Marcin