如何将附加参数传递给 handle_client 协程?
How to pass additional parameters to handle_client coroutine?
将 asyncio 用于套接字服务器的推荐方法是:
import asyncio
async def handle_client(reader, writer):
request = (await reader.read(100)).decode()
response = "Data received."
writer.write(response.encode())
async def main():
loop.create_task(asyncio.start_server(handle_client, 'localhost', 15555))
loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()
这工作正常,但现在我需要接收适当的客户端请求,然后使用 aiohttp 库从第 3 方获取数据 restful API.
这需要创建一个会话变量如下:
from aiohttp import ClientSession
session = ClientSession()
但这也应该在协程本身内部,所以我将其放在 main 中:
async def main():
session = ClientSession()
loop.create_task(asyncio.start_server(handle_client, '', 55555))
现在我需要将会话变量传递给 aiohttp get 协程以获取其余 API 数据:
async with session.get(url, params=params) as r:
try:
return await r.json(content_type='application/json')
except aiohttp.client_exceptions.ClientResponseError:
....
我的问题是如何将会话变量传递给 handle_client 协同程序,如果它坚持只有 reader,writer 参数,并且全局变量对我没有帮助,因为会话必须存在于内部协程?
您可以使用临时函数或 lambda:
async def main():
session = aiohttp.ClientSession()
await asyncio.start_server(lambda r, w: handle_client(r, w, session),
'', 55555)
这是有效的,因为即使 lambda
在技术上不是协程,它的行为就像一个 - 当调用它时 returns a coroutine object.
对于较大的程序,您可能更喜欢基于 class 的方法,其中 class 封装多个客户端共享的状态,而无需显式传递它。例如:
class ClientContext:
def __init__(self):
self.session = aiohttp.ClientSession()
# ... add anything else you will need "globally"
async def handle_client(self, reader, writer):
# ... here you get reader and writer, but also have
# session etc as self.session ...
async def main():
ctx = ClientContext()
await asyncio.start_server(ctx.handle_client), '', 55555)
将 asyncio 用于套接字服务器的推荐方法是:
import asyncio
async def handle_client(reader, writer):
request = (await reader.read(100)).decode()
response = "Data received."
writer.write(response.encode())
async def main():
loop.create_task(asyncio.start_server(handle_client, 'localhost', 15555))
loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()
这工作正常,但现在我需要接收适当的客户端请求,然后使用 aiohttp 库从第 3 方获取数据 restful API.
这需要创建一个会话变量如下:
from aiohttp import ClientSession
session = ClientSession()
但这也应该在协程本身内部,所以我将其放在 main 中:
async def main():
session = ClientSession()
loop.create_task(asyncio.start_server(handle_client, '', 55555))
现在我需要将会话变量传递给 aiohttp get 协程以获取其余 API 数据:
async with session.get(url, params=params) as r:
try:
return await r.json(content_type='application/json')
except aiohttp.client_exceptions.ClientResponseError:
....
我的问题是如何将会话变量传递给 handle_client 协同程序,如果它坚持只有 reader,writer 参数,并且全局变量对我没有帮助,因为会话必须存在于内部协程?
您可以使用临时函数或 lambda:
async def main():
session = aiohttp.ClientSession()
await asyncio.start_server(lambda r, w: handle_client(r, w, session),
'', 55555)
这是有效的,因为即使 lambda
在技术上不是协程,它的行为就像一个 - 当调用它时 returns a coroutine object.
对于较大的程序,您可能更喜欢基于 class 的方法,其中 class 封装多个客户端共享的状态,而无需显式传递它。例如:
class ClientContext:
def __init__(self):
self.session = aiohttp.ClientSession()
# ... add anything else you will need "globally"
async def handle_client(self, reader, writer):
# ... here you get reader and writer, but also have
# session etc as self.session ...
async def main():
ctx = ClientContext()
await asyncio.start_server(ctx.handle_client), '', 55555)