不使用asyncio编写EventLoop

4

我已经对Python的asyncio、Python中的异步编程、协程等内容非常熟悉。我想要能够使用自己制作的事件循环执行多个协程。

我很好奇是否可以完全不导入asyncio来编写自己的事件循环

2个回答

3
我希望能够使用自己定制的事件循环执行多个协程。
asyncio事件循环经过良好测试,可以轻松扩展以承认非asyncio事件。如果您描述实际用例,可能更容易帮助您。但是,如果您的目标是了解异步编程和协程,请继续阅读。
我很好奇是否可以完全不导入asyncio编写自己的事件循环。
这是肯定可能的 - asyncio本身只是一个库 - 但需要花费一些工作让您的事件循环变得有用。请参见David Beazley的精彩演讲,他在现场观众面前演示了编写事件循环的过程。(不要受到David使用较旧的yield from语法的影响 - await的工作方式完全相同。)

1

好的,我在某个地方找到了一个例子(抱歉,不记得在哪里了,没有链接),并稍微修改了一下。

一个没有导入asyncioeventloopco-routins

import datetime
import heapq
import types
import time

class Task:
    def __init__(self, wait_until, coro):
        self.coro = coro
        self.waiting_until = wait_until

    def __eq__(self, other):
        return self.waiting_until == other.waiting_until

    def __lt__(self, other):
        return self.waiting_until < other.waiting_until

class SleepingLoop:
    def __init__(self, *coros):
        self._new = coros
        self._waiting = []

    def run_until_complete(self):
        # Start all the coroutines.
        for coro in self._new:
            wait_for = coro.send(None)
            heapq.heappush(self._waiting, Task(wait_for, coro))

        # Keep running until there is no more work to do.
        while self._waiting:
            now = datetime.datetime.now()
            # Get the coroutine with the soonest resumption time.
            task = heapq.heappop(self._waiting)
            if now < task.waiting_until:
                # We're ahead of schedule; wait until it's time to resume.
                delta = task.waiting_until - now
                time.sleep(delta.total_seconds())
                now = datetime.datetime.now()
            try:
                # It's time to resume the coroutine.
                wait_until = task.coro.send(now)
                heapq.heappush(self._waiting, Task(wait_until, task.coro))
            except StopIteration:
                # The coroutine is done.
                pass


@types.coroutine
def async_sleep(seconds):
    now = datetime.datetime.now()
    wait_until = now + datetime.timedelta(seconds=seconds)
    actual = yield wait_until

    return actual - now


async def countdown(label, total_seconds_wait, *, delay=0):
    print(label, 'waiting', delay, 'seconds before starting countdown')
    delta = await async_sleep(delay)
    print(label, 'starting after waiting', delta)
    while total_seconds_wait:
        print(label, 'T-minus', total_seconds_wait)
        waited = await async_sleep(1)
        total_seconds_wait -= 1
    print(label, 'lift-off!')


def main():
    loop = SleepingLoop(countdown('A', 5, delay=0),
                        countdown('B', 3, delay=2),
                        countdown('C', 4, delay=1))
    start = datetime.datetime.now()
    loop.run_until_complete()

    print('Total elapsed time is', datetime.datetime.now() - start)



if __name__ == '__main__':
    main()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接