最近在家學(xué)習(xí)Python青自,跟著崔老師的網(wǎng)絡(luò)爬蟲課程擼代碼,在看到關(guān)于協(xié)程的時候驱证,提到
在 Python 3.7 及以后的版本中延窜,我們可以使用 asyncio.run(main()) 來代替最后的啟動操作,不需要顯式聲明事件循環(huán)抹锄,run 方法內(nèi)部會自動啟動一個事件循環(huán)逆瑞。
因此想換新的方法試一下,結(jié)果一直出現(xiàn)報錯伙单,提示有另一個事件循環(huán)正在使用呆万,百思不得其解。
當(dāng)時的代碼如下:
import asyncio
import aiohttp
CONCURRENCY = 5
URL = 'https://www.baidu.com'
semaphore = asyncio.Semaphore(CONCURRENCY)
session = None
async def scrape_api():
async with semaphore:
print('scraping', URL)
async with session.get(URL) as response:
await asyncio.sleep(1)
return await response.text()
async def main():
global session
session = aiohttp.ClientSession()
scrape_index_tasks = [asyncio.ensure_future(scrape_api()) for _ in range(100)]
await asyncio.gather(*scrape_index_tasks)
if __name__ == '__main__':
asyncio.run(main())
# asyncio.get_event_loop().run_until_complete(main())
唯一的區(qū)別就是最后的協(xié)程啟動了车份,在把python升級到3.8.5,電腦重啟等一系列神秘操作后牡彻,依然報錯
RuntimeError: Task <Task pending name='Task-7' coro=<scrape_api() running at /Users/zxxx/Desktop/xxx/xxx/xxx.py:11> cb=[gather.<locals>._done_callback() at /usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncio/tasks.py:758]> got Future <Future pending> attached to a different loop
Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x1049987c0>
大概意思就是當(dāng)前循環(huán)存在另一個事件循環(huán)扫沼,而 asyncio.run 的注釋說的很清楚了因此 當(dāng)另一個 asyncio 事件循環(huán)正在當(dāng)前線程運行的時候出爹,不能調(diào)用這個函數(shù)。
但是這里面也沒有單獨開什么線程缎除,搞得很懵逼严就,最后誤打誤撞,把 semaphore 的申明改成和 session 申明一致后器罐,再在main()函數(shù)中把session 關(guān)閉問題就解決了
import asyncio
import aiohttp
CONCURRENCY = 5
URL = 'https://www.baidu.com'
semaphore = None
session = None
async def scrape_api():
async with semaphore:
print('scraping', URL)
async with session.get(URL) as response:
await asyncio.sleep(1)
return await response.text()
async def main():
global semaphore
semaphore = asyncio.Semaphore(CONCURRENCY)
global session
session = aiohttp.ClientSession()
scrape_index_tasks = [asyncio.ensure_future(scrape_api()) for _ in range(100)]
await asyncio.gather(*scrape_index_tasks)
await session.close()
if __name__ == '__main__':
asyncio.run(main())
# asyncio.get_event_loop().run_until_complete(main())
目前還不知道為什么會這樣梢为,先挖個坑看看什么時候能填起來。