Aiohttp、Asyncio: 运行时错误:事件循环已关闭。

7

我有两个脚本,scraper.py和db_control.py。在scraper.py中,我有以下内容:

...
def scrape(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 ]

...

在db_control.py中:

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

理论上,爬虫应该在未知的时间内启动,直到获取足够的数据。但是当new不立即> 15时,就会出现此错误:

  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

但是,如果我只运行一次scrape()函数,脚本可以正常运行。所以我猜想重新创建loop = asyncio.get_event_loop()时存在问题,我尝试过此方法,但是没有任何改变。我该如何解决这个问题呢?当然,这些只是我的代码片段,如果您认为问题可能出现在其他地方,完整的代码可以在这里找到。

请注意,这里的正确拼写是“scraper”(和“scrape”,“scraped”,“scraping”),而不是“scrapper”。 - DisappointedByUnaccountableMod
1个回答

8

方法 run_until_completerun_foreverrun_in_executorcreate_taskcall_at 明确检查循环并在关闭时抛出异常。

引用自文档 - BaseEvenLoop.close:

这是幂等和不可逆的


除非有一些(好的)理由,否则您可以省略关闭行:

def scrape(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 ]

如果您想每次都拥有一个全新的循环,您需要手动创建并将其设置为默认值:

def scrape(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 ]

谢谢!现在工作得就像魔法一样 :) - Peter Jung
第一个代码片段中的loop应该关闭吗?如果是,应该在哪里关闭? - jdhao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接