首页 文章

尝试发出异步请求时,RuntimeError会话关闭

提问于
浏览
0

首先是代码:

import random
import asyncio
from aiohttp import ClientSession
import csv

headers =[]

def extractsites(file):
    sites = []
    readfile = open(file, "r")
    reader = csv.reader(readfile, delimiter=",")
    raw = list(reader)
    for a in raw:
        sites.append((a[1]))
    return sites


async def fetchheaders(url, session):
    async with session.get(url) as response:
        responseheader = await response.headers
        print(responseheader)
        return responseheader


async def bound_fetch(sem, url, session):
    async with sem:
        print("doing request for "+ url)
        await fetchheaders(url, session)


async def run():
    urls = extractsites("cisco-umbrella.csv")
    tasks = []
    # create instance of Semaphore
    sem = asyncio.Semaphore(100)
    async with ClientSession() as session:
        for i in urls:
            task = asyncio.ensure_future(bound_fetch(sem, "http://"+i, session))
            tasks.append(task)
        return tasks

def main():
    loop = asyncio.get_event_loop()
    future = asyncio.ensure_future(run())
    loop.run_until_complete(future)

if __name__ == '__main__':
    main()

大部分代码都来自这篇博文:https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html

这是我面临的问题:我试图从文件中读取一百万个网址,然后为每个网址发出异步请求 . 但是当我尝试执行上面的代码时,我得到了Session过期错误 .

这是我的想法:我对异步编程比较新,所以请耐心等待 . 我的过程是创建一个长任务列表(只允许100个并行请求),我在 run 函数中构建,然后作为 future 传递给事件循环执行 .

我在bound_fetch(我从博客文章中复制过)中包含了一个打印调试,看起来它遍历了我拥有的所有url,并且一旦它应该开始在 fetchheaders 函数中发出请求,我就会收到运行时错误 .

如何修复代码?

1 回答

  • 2

    这里有几件事 .

    首先,在您的运行功能中,您实际上想要在那里收集任务并等待他们修复会话问题,如下所示:

    async def run():
        urls = ['google.com','amazon.com']
        tasks = []
        # create instance of Semaphore
        sem = asyncio.Semaphore(100)
        async with ClientSession() as session:
            for i in urls:
                task = asyncio.ensure_future(bound_fetch(sem, "http://"+i, session))
                tasks.append(task)
            await asyncio.gather(*tasks)
    

    其次,aiohttp API在处理 Headers 方面有点奇怪,因为你无法等待它们 . 我通过等待正文来解决这个问题,以便填充 Headers 然后返回 Headers :

    async def fetchheaders(url, session):
        async with session.get(url) as response:
            data = await response.read()
            responseheader = response.headers
            print(responseheader)
            return responseheader
    

    然而,拉动身体还有一些额外的开销 . 虽然没有进行正文读取,但我找不到另一种加载 Headers 的方法 .

相关问题