Future 和 Task对象
import uuid
class Future:
def __init__(self, loop):
self._result = None
self._done = False
self._callbacks = []
self._loop = loop
def set_result(self, data):
if self._done:
raise RuntimeError("Future 对象不能重复设置值")
self._done = True
self._result = data
if isinstance(data, Future):
self._result = data._result
for callback in self._callbacks:
self._loop.add_ready_task(callback)
def result(self):
if self._done:
return self._result
raise RuntimeError("Future对象 值结果还没就绪")
def __await__(self):
yield self
return self._result
def add_done_callback(self, callback, *args):
self._callbacks.append(callback)
class Task(Future):
def __init__(self, core, loop):
super(Task, self).__init__(loop)
self.core = core
self._task_id = uuid.uuid4()
self._future = None
def run(self):
try:
print(f"{self._task_id} 任务 开始执行")
future = self.core.send(None)
except StopIteration:
self.set_result(self._future)
print(f"{self._task_id} 协程任务 执行结束")
print("-" * 50)
else:
print(f"{self._task_id} 任务 执行到io耗时操作,将执行权让出去,设置io回调通知")
print("-" * 50)
future.add_done_callback(self)
self._future = future
EventLoop 事件循环对象
import collections
import heapq
import time
from random import random, randint
from threading import Thread
from async_future_task import Future, Task
class EventLoop:
loop = None
def __new__(cls, *args, **kwargs):
if not cls.loop:
cls.loop = super().__new__(cls)
return cls.loop
def __init__(self):
self._ready_que = collections.deque()
self._scheduled = []
self.stop = False
def create_task(self, core, *args):
task = Task(core, self)
self._ready_que.append(task)
return task
def add_delay_task(self, delay, callback, *args):
t = time.time() + delay
heapq.heappush(self._scheduled, (t, callback, args))
def add_ready_task(self, task, *args):
self._ready_que.append(task)
def run_forever(self):
while True:
self.exec_task()
if self.stop and len(self._scheduled) == 0 and len(self._ready_que) == 0:
break
def stop_exit(self):
self.stop = True
def exec_task(self):
t = time.time()
len_scheduled = len(self._scheduled)
for i in range(len_scheduled):
task = heapq.heappop(self._scheduled)
if task[0] <= t:
self._ready_que.append((task[1], task[2]))
else:
heapq.heappush(self._scheduled, task)
break
len_ready = len(self._ready_que)
for i in range(len_ready):
task = self._ready_que.popleft()
if isinstance(task, Task):
task.run()
else:
task[0](*task[1])
async def get_baidu():
data = await aiohttp_request_url()
print("异步任务结束, io操作获取到的值是: ", data)
return data
async def aiohttp_request_url():
future = Future(loop)
fake_io(future)
data = await future
return data
def fake_io(future):
def sleep():
global task_run_time
task_time = random()
task_run_time += task_time
time.sleep(task_time)
data = randint(1, 10)
future.set_result(data)
Thread(target=sleep).start()
loop = EventLoop()
start_time = time.time()
task_run_time = 0
for _ in range(1000):
loop.create_task(get_baidu())
loop.add_delay_task(2, loop.stop_exit)
loop.run_forever()
print(f"所有任务执行时间:{task_run_time}, 实际执行时间{time.time() - start_time}")
理解图
![请添加图片描述](https://i-blog.csdnimg.cn/blog_migrate/3ad3fcb6623e9c183b706736180a2259.png)
参考b站大佬 DavyCloud asyncio系列教程