美文网首页
Python 协程学习中遇到的asyncio.run(main(

Python 协程学习中遇到的asyncio.run(main(

作者: 木菀 | 来源:发表于2020-11-04 19:22 被阅读0次

最近在家学习Python,跟着崔老师的网络爬虫课程撸代码,在看到关于协程的时候,提到

在 Python 3.7 及以后的版本中,我们可以使用 asyncio.run(main()) 来代替最后的启动操作,不需要显式声明事件循环,run 方法内部会自动启动一个事件循环。
因此想换新的方法试一下,结果一直出现报错,提示有另一个事件循环正在使用,百思不得其解。
当时的代码如下:

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

唯一的区别就是最后的协程启动了,在把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>
大概意思就是当前循环存在另一个事件循环,而 asyncio.run 的注释说的很清楚了 image.png

因此 当另一个 asyncio 事件循环正在当前线程运行的时候,不能调用这个函数。
但是这里面也没有单独开什么线程,搞得很懵逼,最后误打误撞,把 semaphore 的申明改成和 session 申明一致后,再在main()函数中把session 关闭问题就解决了

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

目前还不知道为什么会这样,先挖个坑看看什么时候能填起来。

相关文章

  • Python 协程学习中遇到的asyncio.run(main(

    最近在家学习Python,跟着崔老师的网络爬虫课程撸代码,在看到关于协程的时候,提到 在 Python 3.7 及...

  • Python 协程的基本概念

    Python 协程的基本概念 在学习 Python 基础的过程中,遇到了比较难理解的地方,那就是协程。刚开始看了廖...

  • asyncio 初学记录 (一、协程和任务)

    1.asyncio.run() 可以单独运行协程asyncio.run() 结果 2.asyncio.create...

  • Python 协程

    仅供学习,转载请注明出处 协程 协程,又称微线程,纤程。英文名Coroutine。 协程是啥 协程是python个...

  • python异步协程(aiohttp,asyncio)

    python异步协程 环境:python3.7.0 协程 协程,英文叫做 Coroutine,又称微线程,纤程,协...

  • python 协程 1:yield 10分钟入门

    协程定义 协程的底层架构是在pep342 中定义,并在python2.5 实现的。 python2.5 中,yie...

  • Python基础学习之六yield

    协程定义 协程的底层架构是在pep342 中定义,并在python2.5 实现的。 python2.5 中,yie...

  • 多任务-协程

    一、协程的概念 协程,又称微线程,纤程。英文名Coroutine。协程是python中另外一种实现多任务的方式,只...

  • asyncio + asyncio 异步编程实例

    协程用法 接下来,我们来了解下协程的实现,从 Python 3.4 开始,Python 中加入了协程的概念,但这个...

  • Python 协程学习

    协程本质上仍然是一个线程,其能够在多个任务之间切换来节省一些 IO 时间。 greenlet 模块来支持 协程一般...

网友评论

      本文标题:Python 协程学习中遇到的asyncio.run(main(

      本文链接:https://www.haomeiwen.com/subject/jftnvktx.html