- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试制作一款可以使用一天、一周或更长时间的应用。在应用程序的生命周期中,它会向不同的 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 session
和 Unclosed 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/
我想要一个类似于 django runserver 所做的重新加载。 如果我更改 python 文件,我希望应用程序重新加载。我已经安装了 aiohttp-devtools 并使用 adev runs
我在使用 RouteTableDef 时遇到问题。 有一些项目的路由结构如下: 1) 有文件route.py。 路线.py from aiohttp import web routes = web.R
我有一些代码对某些 API 进行请求序列。我想为所有人设置通用日志记录,我该如何设置? 假设我的代码是这样的 import aiohttp import asyncio async def fetch
您能否就以下方面提出建议? 在 localhost:8900 上有 aiohttp 服务器在运行 当我从 python 发出类似(使用 python2 模块请求)的请求时 requests.get("
每当我对使用 asyncio 和 aiohttp 访问的 API 执行超过 200 个请求时,我都会收到 aiohttp client_exception.ServerDisconnectedErro
在我正在开发的爬虫中。它使用 pycurl multi 发出请求。 如果我改用aiohttp,我可以期待什么样的效率提升? 怀疑让我怀疑潜在的改进,因为 python 有 GIL。大部分时间都花在等待
我在尝试使用 azure 测试聊天机器人时遇到一些问题: 我使用 github actions 在 azure web 应用程序上部署了我的机器人,一切都很顺利。但是当我尝试测试我的聊天机器人时,没有
我在尝试使用 azure 测试聊天机器人时遇到一些问题: 我使用 github actions 在 azure web 应用程序上部署了我的机器人,一切都很顺利。但是当我尝试测试我的聊天机器人时,没有
我想知道如何从 aiohttp post 方法获取当前的上传步骤。通常我会使用 get 方法在循环中拉取当前步骤,但如果主机不响应当前上传步骤,这将不起作用。那么有可能得到当前步骤吗?诸如“从 xx%
我目前正在用 aiohttp 做我的第一个“婴儿学步” (来自 requests 模块)。 我尝试稍微简化请求,这样我就不必在主模块中为每个请求使用上下文管理器。 因此我尝试了这个: async de
tl;dr:如何最大化可以并行发送的 http 请求数量? 我正在使用 aiohttp 库从多个网址获取数据。我正在测试它的性能,并且观察到该过程中的某个地方存在瓶颈,一次运行更多的网址并没有帮助。
目前我正在执行以下操作来获取当前正在运行的应用程序 async def handler(request): app = request.app 是否有其他方法来获取当前正在运行的应用程序?考虑
首先是代码: import random import asyncio from aiohttp import ClientSession import csv headers =[] def ext
我的 aiohttp 中间件获取函数作为参数,而不是已传递给路由的绑定(bind)方法。如何解释这种行为?如何避免这种情况? class AsyncHttpServer: def __init
我正在尝试在 aiohttp 处理程序中启动后台长时间任务: from aiohttp import web import time import asyncio async def one(requ
我正在测试 aiohttp 和 asyncio。我希望相同的事件循环具有套接字、http 服务器、http 客户端。 我正在使用此示例代码: @routes.get('/') async def he
#!/usr/bin/env python3.5 import asyncio import aiohttp url = "http://eniig.dk" async def main():
考虑以下代码: from aiohttp_mako import template def authorize(): def wrapper(func): @asyncio.c
我正在编写一个网络爬虫,它为许多不同的域运行并行提取。我想限制每秒向每个单独的域发出的请求数,但我不关心打开的连接总数或每秒的总请求数跨越所有领域。 我想最大限度地提高打开的连接数和每秒请求数,同时限
我需要将 sub_app 添加到 sub_app。这是我的代码 app = web.Application() subapp = web.Application() subapp.router.add
我是一名优秀的程序员,十分优秀!