2016-06-12 35 views
6

Ho due script, scraper.py e db_control.py. In scraper.py ho qualcosa di simile a questo:Aiohttp, Asyncio: RuntimeError: il ciclo di eventi è chiuso

... 
def scrap(category, field, pages, search, use_proxy, proxy_file): 
    ... 
    loop = asyncio.get_event_loop() 

    to_do = [ get_pages(url, params, conngen) for url in urls ] 
    wait_coro = asyncio.wait(to_do) 
    res, _ = loop.run_until_complete(wait_coro) 
    ... 
    loop.close() 

    return [ x.result() for x in res ] 

... 

E in db_control.py:

from scraper import scrap 
... 
while new < 15: 
    data = scrap(category, field, pages, search, use_proxy, proxy_file) 
    ... 
... 

Teoricamente, dovrebbe essere avviata scrapper sconosciuti volte fino a quando abbastanza di dati sono stati ottenuti. Ma quando new non è imidiatelly > 15 allora questo errore si verifica:

File "/usr/lib/python3.4/asyncio/base_events.py", line 293, in run_until_complete 
self._check_closed() 
    File "/usr/lib/python3.4/asyncio/base_events.py", line 265, in _check_closed 
raise RuntimeError('Event loop is closed') 
RuntimeError: Event loop is closed 

Ma script funziona bene se corro rottami() una sola volta. Quindi immagino ci sia qualche problema con il ricreare loop = asyncio.get_event_loop(), ho provato this ma non è cambiato nulla. Come posso risolvere questo? Naturalmente quelli sono solo frammenti del mio codice, se pensi che il problema possa essere altrove, il codice completo è disponibile here.

risposta

7

Metodi run_until_complete, run_forever, run_in_executor, create_task, call_at controllare esplicitamente il ciclo e gettare un'eccezione se è chiuso.

Citazione di documenti - BaseEvenLoop.close:

This is idempotent and irreversible


A meno che non si dispone di alcuni (buone) ragioni, si potrebbe semplicemente omettere la stretta linea:

def scrap(category, field, pages, search, use_proxy, proxy_file): 
    #... 
    loop = asyncio.get_event_loop() 

    to_do = [ get_pages(url, params, conngen) for url in urls ] 
    wait_coro = asyncio.wait(to_do) 
    res, _ = loop.run_until_complete(wait_coro) 
    #... 
    # loop.close() 
    return [ x.result() for x in res ] 

Se si desidera avere ogni volta un nuovo ciclo, è necessario crearlo manualmente e impostare come predefinito:

def scrap(category, field, pages, search, use_proxy, proxy_file): 
    #... 
    loop = asyncio.new_event_loop() 
    asyncio.set_event_loop(loop)  
    to_do = [ get_pages(url, params, conngen) for url in urls ] 
    wait_coro = asyncio.wait(to_do) 
    res, _ = loop.run_until_complete(wait_coro) 
    #... 
    return [ x.result() for x in res ] 
+0

Grazie! Funziona come un fascino ora :) –