问题描述
对套接字服务器使用asyncio的推荐方法是:
The recommended way to use asyncio for a socket server is:
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库从第三方的Restful API获取数据。
This works fine, but now I need to receive appropriate client request and then use aiohttp library to fetch data from a 3rd party restful API.
这需要创建如下的会话变量:
This requires creating a session variable as follows:
from aiohttp import ClientSession
session = ClientSession()
但这也应该放在协程自身中,所以我将将其放入main:
But this also should be inside a coroutine itself, so I'll put it inside main:
async def main():
session = ClientSession()
loop.create_task(asyncio.start_server(handle_client, '', 55555))
现在我需要通过会话变量aiohttp获取协程以获取其余API数据:
Now I need to pass the session variable to the aiohttp get coroutine to fetch the rest API data:
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协程?
My question is how can I pass the session variable to handle_client coroutine, if it insists on only having reader,writer parameters, and globals don't help me because sessions must exist inside coroutines?
推荐答案
您可以使用临时函数或lambda:
You can use a temporary function or a lambda:
async def main():
session = aiohttp.ClientSession()
await asyncio.start_server(lambda r, w: handle_client(r, w, session),
'', 55555)
之所以可以这样做是因为即使 lambda
从技术上讲不是协程,它的行为就像一个协程-它是可调用的,返回一个
This works because even though the lambda
is not technically a coroutine, it behaves like one - it is a callable that returns a coroutine object when invoked.
对于大型程序,您可能更喜欢基于类的方法,该类封装了状态共享由多个客户使用,而不必将它们从协程传递到协程。例如:
For larger programs you might prefer a class-based approach with a class encapsulating the state shared by multiple clients without having to pass it from coroutine to coroutine. For example:
class ClientContext:
def __init__(self, session):
self.session = session
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(aiohttp.ClientSession())
await asyncio.start_server(ctx.handle_client), '', 55555)
这篇关于如何将其他参数传递给handle_client协程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!