2016-06-12 28 views
6

Mam dwa skrypty: scraper.py i db_control.py. W scraper.py mam coś takiego:Aiohttp, Asyncio: RuntimeError: pętla zdarzeń jest zamknięta

... 
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 ] 

... 

aw db_control.py:

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

Teoretycznie scrapper powinny być rozpoczęte unknown-razy, aż na tyle dane zostały uzyskane. Ale kiedy new nie jest imidiatelly > 15 wtedy ten błąd:

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 

ale skrypty działa dobrze, jeśli biegnę złom() tylko raz. Sądzę, że jest jakiś problem z odtworzeniem loop = asyncio.get_event_loop(), próbowałem this, ale nic się nie zmieniło. Jak mogę to naprawić? Oczywiście są to tylko fragmenty mojego kodu, jeśli uważasz, że problem może być gdzie indziej, pełny kod jest dostępny here.

Odpowiedz

7

Metody run_until_complete, run_forever, run_in_executor, create_task, call_at jednoznacznie sprawdzić pętli i rzucić wyjątek, jeśli jest zamknięta.

Cytat docs - BaseEvenLoop.close:

This is idempotent and irreversible


Chyba że masz jakieś (dobrze) powody, można po prostu pominąć ścisłą linię:

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 ] 

Jeśli chcesz mieć każdy czas zupełnie nowej pętli, musisz ją utworzyć ręcznie i ustawić jako domyślną:

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

Dzięki! Działa jak urok teraz :) –