V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
rainto
V2EX  ›  Python

asyncio 批量获取需要 await 的对象为空,请表哥们指教

  •  
  •   rainto · 2019-07-25 10:58:31 +08:00 · 1685 次点击
    这是一个创建于 1952 天前的主题,其中的信息可能已经有所发展或是发生改变。

    起因是我要用到协程去批量验证多个 http 地址情况:当前 url 地址 ,http 状态 ,title

    import asyncio,aiohttp
    from bs4 import BeautifulSoup
    res=[]
    async def fetch_async(url):
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                url=resp.url
                status=resp.status
                text=await resp.read()
                soup = BeautifulSoup(text, 'lxml')
                title=soup.title.string
                print(url,status,title)
                #res.append(url,status,title)
                
    tasks = [fetch_async('http://www.baidu.com/'), fetch_async('https://www.v2ex.com')]
    
    event_loop = asyncio.get_event_loop()
    results = event_loop.run_until_complete(asyncio.gather(*tasks))
    event_loop.close()
    
    http://www.baidu.com/ 200 百度一下,你就知道
    https://www.v2ex.com 200 V2EX
    

    遵从一个函数只干一件事的原则,于是我将整个 response 对象返回到列表里了,一切 ok .

    就当我要把它们取出的时候 。

    for i in res: i.url —>https;//xx.com i.status —>200 i.read() ->null 由于 response 的 read() 要使用 await 不然是获取不到的。

    我尝试 :

    res.append(await response) print(len(res)) --> 0

    现在是没有办法了,还望表哥们给点思路

    6 条回复    2019-07-25 22:24:59 +08:00
    ethego
        1
    ethego  
       2019-07-25 11:26:19 +08:00
    1. `asyncio.create_task(fetch_async('http://www.baidu.com/'))`
    2. 用 queue 而不是 list,并发执行是这里有竞争
    keepeye
        2
    keepeye  
       2019-07-25 11:35:44 +08:00
    遵从一个函数只干一件事的原则,于是我将整个 response 对象返回到列表里了

    -----

    你为何不将 response 读出来放到 res 里呢? 好好想想如何界定"一件事"
    so1n
        3
    so1n  
       2019-07-25 13:37:19 +08:00
    你必须在 async with session.get(url) as resp:这个上下文里面 await resp.read()或者 await resp.text() 你离开这个上下文这个链接已经关闭了,你就再也不能从这个 response 里面获取数据.
    rainto
        4
    rainto  
    OP
       2019-07-25 14:46:38 +08:00
    @so1n 将整个 response 对象存起来,只能存到当时的状态,需要 await 的属性 就再也拿不到了嘛。
    那我也有尝试过 append(await response ) 还是不可以
    wwqgtxx
        5
    wwqgtxx  
       2019-07-25 20:45:48 +08:00
    @rainto aiohttp 的 response 是惰性读取的,也就是只有你在 await resp.read()的时候才会真正的从 TCP 缓冲区读取,当你关闭这个 resp 的时候,http 连接已经关闭,就不可能读到数据了
    当然你 await response 有什么用,这样既不会真正的读取,aiohttp 的 response 对象也不是可重用的,你只能自己 new 一个 dict 来把 resp 中你想要的数据保存出来,再 append 进 res
    so1n
        6
    so1n  
       2019-07-25 22:24:59 +08:00
    @rainto 是的。response,只是带有一个从缓冲区取数据的方法,但你离开缓冲区了(不在 response 上下文),要去调用这个方法取数据也取不到数据了,你需要在没离开前取出数据 例如一个不是很好的实例 response.text = await response.text() 之后你就能从 response.text 拿到数据了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5467 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 07:42 · PVG 15:42 · LAX 23:42 · JFK 02:42
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.