解决回调函数只能传一个值的问题
解决方案就是使用改造回调函数为闭包函数,原理就是调用闭包函数时,没有参数限制,这个时候我们可以任意传递参数。
然后该闭包返回的是真正的回调函数callback,这个callback中我们只写一个形参就完了。
python
# -*- coding = utf-8 -*-
import os
import asyncio
import aiohttp
from threading import Thread
policy = asyncio.WindowsSelectorEventLoopPolicy()
asyncio.set_event_loop_policy(policy)
semaphore = asyncio.Semaphore(os.cpu_count())
headers = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
}
def content_type_map(content_type, response):
ctm = {
"application/json": response.json,
"text/html": response.text,
}
return ctm[content_type]() if content_type in ctm else response.read()
async def get_request(url):
""" 基于aiohttp实现的异步协程对象(一组操作集) """
async with semaphore:
async with aiohttp.ClientSession(trust_env=True) as session:
async with await session.request(method='get', url=url, headers=headers) as response:
result = await content_type_map(response.headers.get('content-type'), response)
return result
def task_callback(cb):
"""
任务对象的回调函数,该回调函数有且只有一个参数
:param cb: 该回调函数的调用者,即任务对象
:return:
"""
print('回调函数执行成功', type(cb.result()), cb.result())
def task_callback2(x1, x2, x3):
"""
任务对象的回调闭包函数,原理就是调用闭包函数时,没有参数限制,
然后该闭包返回的是真正的回调函数callback,这个callback中我们只写一个形参就完了
"""
def callback(cb):
print('回调函数执行成功', x1, x2, x3, cb.result())
return callback
def event_loop_server_forever(loop):
""" 事件循环服务器的永久运行事件 """
asyncio.set_event_loop(loop)
loop.run_forever()
async def work():
new_loop = asyncio.new_event_loop()
t = Thread(target=event_loop_server_forever, args=(new_loop,))
t.start()
for i in range(5):
url = f'http://httpbin.org/get?id={i}'
future = asyncio.run_coroutine_threadsafe(get_request(url), new_loop)
# future.add_done_callback(task_callback) # 默认的回调只能有一个参数
# 如果有需要在回调中额外的传递参数,可以将回调函数写成闭包的形式,能额外传递任意参数
future.add_done_callback(task_callback2('x1', 'x2', 'x3'))
print('主线程继续执行')
t.join()
if __name__ == '__main__':
asyncio.run(work())