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

2019-07-25 10:58:31 +08:00
 rainto

起因是我要用到协程去批量验证多个 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

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

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

-----

你为何不将 response 读出来放到 res 里呢? 好好想想如何界定"一件事"
so1n
2019-07-25 13:37:19 +08:00
你必须在 async with session.get(url) as resp:这个上下文里面 await resp.read()或者 await resp.text() 你离开这个上下文这个链接已经关闭了,你就再也不能从这个 response 里面获取数据.
rainto
2019-07-25 14:46:38 +08:00
@so1n 将整个 response 对象存起来,只能存到当时的状态,需要 await 的属性 就再也拿不到了嘛。
那我也有尝试过 append(await response ) 还是不可以
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
2019-07-25 22:24:59 +08:00
@rainto 是的。response,只是带有一个从缓冲区取数据的方法,但你离开缓冲区了(不在 response 上下文),要去调用这个方法取数据也取不到数据了,你需要在没离开前取出数据 例如一个不是很好的实例 response.text = await response.text() 之后你就能从 response.text 拿到数据了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/586040

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX