gpt4 book ai didi

python - 如何关闭aiohttp ClientSession

转载 作者:太空宇宙 更新时间:2023-11-04 09:39:25 29 4
gpt4 key购买 nike

我正在尝试制作一款可以使用一天、一周或更长时间的应用。在应用程序的生命周期中,它会向不同的 API 发出请求。其中一些 api 可能需要登录,因此重要的是我随时可以访问 cookie。

所以我需要的是一个文件,不同的 API 可以在不阻止应用程序的情况下使用它。

我是异步编程 (asyncio/aiohttp) 的新手,我看到的示例展示了如何从 url 列表发出大量请求,但这不是我需要的。

我的代码的问题是,要么我收到 ClientSession is closed 错误,要么收到 Unclosed ClientSession 警告。

import asyncio  # only here for debugging purposes
import aiohttp

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:61.0) Gecko/20100101 Firefox/61.1'


def default_headers():
header = {
'User-Agent': USER_AGENT
}
return header


class WebSession(object):
session = None

@classmethod
def create(cls):
cls.session = aiohttp.ClientSession()
return cls.session

@classmethod
def close(cls):
if cls.session is not None:
cls.session.close()

async def request(method, url, **kwargs):

if kwargs.get('headers', None) is None:
kwargs['headers'] = default_headers()

if WebSession.session is None:
session = WebSession.create()
else:
session = WebSession.session


async with session.request(method=method, url=url, **kwargs) as response:
if isinstance(session, aiohttp.ClientSession):
# if i close the session here, i will get the ClientSession closed error on 2. request.
# await session.close()
pass

return response


async def get(url, **kwargs):
return await request('GET', url=url, **kwargs)


async def post(url, **kwargs):
return await request('POST', url=url, **kwargs)


async def get_url():
res = await get('https://httpbin.org/get')
print(f'Status code: {res.headers}')


m_loop = asyncio.get_event_loop()
m_loop.run_until_complete(get_url())
# if i run this without closing the ClientSession, i will get unclosed ClientSession warnings.
m_loop.run_until_complete(get_url())
m_loop.close()

我确实收到了来自服务器的响应,但是它后面跟着这个错误/警告

Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x03354630>
Unclosed connector
connections: ['[(<aiohttp.client_proto.ResponseHandler object at 0x033BBBF0>, 71.542)]']
connector: <aiohttp.connector.TCPConnector object at 0x033542D0>

如果我取消注释 await session.close() 并删除 pass 我会在第一个请求中收到来自服务器的响应,然后是 RuntimeError: session 在第二个请求中关闭

最佳答案

啊,我想我现在明白了。

我收到 Unclosed client sessionUnclosed connector 的警告是 aiohttp 告诉我“嘿,你忘了关闭 session ”。这正是这个小例子所发生的事情。对 get_url 的两次调用实际上都会从服务器获得响应,然后应用程序就会结束。因此,当应用程序结束时, session 将处于未关闭状态,这就是显示上述警告的原因。

我不应该在每次请求后关闭 session ,因为此时无法发出新请求,至少据我所知是这样。这就是为什么我在尝试发出新请求时得到 RuntimeError: Session is closed,一旦它已经关闭。

所以一旦我弄明白了这一点,我就创建了一个关闭函数,并在循环(应用程序)结束之前简单地调用了它。现在我没有收到任何警告/错误。并且 cookie 现在在应用程序运行时在所有请求之间共享(我认为)。无论是 GET 还是 POST,这正是我想要的。

我希望 aiohttp/asyncio 的其他新手能从中受益,因为我花了一些时间(很长)来理解。因为我还是 aiohttp/asyncio 的新手,我不知道这是否是正确的做法,但至少它似乎有效。

import asyncio  # only here for debugging purposes
import aiohttp

USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:61.0) Gecko/20100101 Firefox/61.1'


def default_headers():
header = {
'User-Agent': USER_AGENT
}
return header


class WebSession(object):
session = None

@classmethod
def create(cls):
cls.session = aiohttp.ClientSession()
return cls.session

@classmethod
def close(cls):
if cls.session is not None:
# apparently this is supposed to return a future?
return cls.session.close()


async def request(method, url, **kwargs):

if kwargs.get('headers', None) is None:
kwargs['headers'] = default_headers()

if WebSession.session is None:
session = WebSession.create()
else:
session = WebSession.session

return await session.request(method=method, url=url, **kwargs)


async def get(url, **kwargs):
return await request('GET', url=url, **kwargs)


async def post(url, **kwargs):
return await request('POST', url=url, **kwargs)


async def get_url():
res = await get('https://httpbin.org/get')
print(f'Headers: {res.headers}')


async def close():
# run this before the app ends
await WebSession.close()

# so imagine that this is our app.
m_loop = asyncio.get_event_loop()
# its running now and doing stuff..

# then it makes a request to a url.
m_loop.run_until_complete(get_url())
# then some time passes, and then it makes another request to a url.
m_loop.run_until_complete(get_url())
# now the app gets stopped, whether by keyboard interrupt or some other means of stopping it
# then close the session
m_loop.run_until_complete(close())
# and then end the app..
m_loop.close()

关于python - 如何关闭aiohttp ClientSession,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52228550/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com