Python 3.x 为什么在使用aiohttp模块时必须使用async with?

Python 3.x 为什么在使用aiohttp模块时必须使用async with?,python-3.x,python-requests,python-asyncio,aiohttp,Python 3.x,Python Requests,Python Asyncio,Aiohttp,在Python中使用asyncio和aiohttp编写异步爬虫程序时,我一直有一个问题:为什么必须使用async with,如果不使用它们,很容易报告错误 尽管aiohttp也有一个方法request,但它可以支持调用更简单的api。我想知道有什么不同。我仍然非常喜欢请求模块,我不知道它是否能像请求模块那样简单 为什么必须使用async with 它不像您必须使用async with,它只是一个故障保护设备,用于确保资源得到清理。举一个典型的例子: 您可以将其重新编写为: async def f

在Python中使用
asyncio
aiohttp
编写异步爬虫程序时,我一直有一个问题:为什么必须使用
async with
,如果不使用它们,很容易报告错误

尽管
aiohttp
也有一个方法
request
,但它可以支持调用更简单的api。我想知道有什么不同。我仍然非常喜欢
请求
模块,我不知道它是否能像
请求
模块那样简单

为什么必须使用
async with

它不像您必须使用
async with
,它只是一个故障保护设备,用于确保资源得到清理。举一个典型的例子:

您可以将其重新编写为:

async def fetch(session, url):
    response = await session.get(url)
    return await response.text()
此版本的工作方式似乎相同,但它不会关闭响应对象,因此某些操作系统资源(例如,底层连接)可能会继续无限期保留。更正确的版本如下所示:

async def fetch(session, url):
    response = await session.get(url)
    content = await response.text()
    response.close()
    return content
如果在读取文本时引发异常,此版本仍将无法关闭响应。它可以通过使用
最终解决
——这正是
使用
异步使用
在引擎盖下所做的。使用
async With
块,代码更加健壮,因为该语言确保在执行离开块时调用清理代码

为什么必须使用
async with

它不像您必须使用
async with
,它只是一个故障保护设备,用于确保资源得到清理。举一个典型的例子:

您可以将其重新编写为:

async def fetch(session, url):
    response = await session.get(url)
    return await response.text()
此版本的工作方式似乎相同,但它不会关闭响应对象,因此某些操作系统资源(例如,底层连接)可能会继续无限期保留。更正确的版本如下所示:

async def fetch(session, url):
    response = await session.get(url)
    content = await response.text()
    response.close()
    return content

如果在读取文本时引发异常,此版本仍将无法关闭响应。它可以通过使用
最终解决
——这正是
使用
异步使用
在引擎盖下所做的。使用
async With
块,代码更加健壮,因为该语言确保在执行离开块时调用清理代码。

请考虑您的答案。但是我仍然有一个问题想知道为什么异步是重要的。@hfldqwe在最后一段中回答了这个问题。如果某些部分不清楚,请具体说明,以便我可以对其进行改进。很抱歉现在回复,我有一个地方不明白:我在文档(以及许多其他解释)中强调了我希望使用async,但不允许使用它。async with存在一个问题(即会话未关闭),我不知道Python的对象回收机制是否可以处理这个问题。如果我在我的项目中使用aiohttp作为爬虫程序,并使用tornado编写后端接口,那么在tornado的RequestHandler中编写异步似乎非常困难。通常我会这样做Async def login(self、client、username、password'):…与client.post(url.login\u url(),headers=url.headers,data=data)异步,作为resp:Result=wait resp.json()#如果Result['success',确定登录是否成功==True:Return resp.cookies`````与aiohttp.ClientSession(cookie\u jar=jar)异步作为客户端:cookies=wait spider.login(客户端,用户名=用户名,密码=密码)``但是在tornado中,我不能将客户端作为参数传递给我的爬虫。例如:``Class InfoHandler(BaseHandler):''返回个人信息'''Async def get(self):与aiohttp.ClientSession()作为客户端进行异步:Result=wait spider.login(client,username='xxx',password='xxx')``这会为每个链接创建一个会话,这是一种资源浪费,不建议在aiohttp中使用。我该怎么做?我想你的答案。但是我仍然有一个问题想知道为什么异步是重要的。@hfldqwe在最后一段中回答了这个问题。如果某些部分不清楚,请具体说明,以便我可以对其进行改进。很抱歉现在回复,我有一个地方不明白:我在文档(以及许多其他解释)中强调了我希望使用async,但不允许使用它。async with存在一个问题(即会话未关闭),我不知道Python的对象回收机制是否可以处理这个问题。如果我在我的项目中使用aiohttp作为爬虫程序,并使用tornado编写后端接口,那么在tornado的RequestHandler中编写异步似乎非常困难。通常我会这样做Async def login(self、client、username、password'):…与client.post(url.login\u url(),headers=url.headers,data=data)异步,作为resp:Result=wait resp.json()#如果Result['success',确定登录是否成功==True:Return resp.cookies`````与aiohttp.ClientSession(cookie\u jar=jar)异步作为客户端:cookies=wait spider.login(客户端,用户名=用户名,密码=密码)``但是在tornado中,我不能将客户端作为参数传递给我的爬虫。例如:``Class InfoHandler(BaseHandler):''返回个人信息'''Async def get(self):与aiohttp.ClientSession()作为客户端进行异步:Result=wait spider.login(client,username='xxx',password='xxx')``这会为每个链接创建一个会话,这是一种资源浪费,不建议在aiohttp中使用。我该怎么做?