代码之家  ›  专栏  ›  技术社区  ›  Aaron_ab

不使用asyncio编写EventLoop

  •  0
  • Aaron_ab  · 技术社区  · 6 年前

    异步 ,python异步编程,co例程等。 事件循环

    我很好奇我是否能自己写 不进口 异步

    2 回复  |  直到 6 年前
        1
  •  3
  •   user4815162342    6 年前

    我希望能够使用自己定制的eventloop执行多个co例程。

    asyncio事件循环经过良好测试,可以轻松扩展以确认非asyncio事件。如果您描述实际的用例,可能会更容易提供帮助。但是如果你的目标是 学习 关于异步编程和协同程序,请继续阅读。

    这当然是可能的——毕竟asyncio本身只是一个库——但要使事件循环变得有用还需要一些工作。看见 this excellent talk yield from 语法- await 工作原理完全相同。)

        2
  •  1
  •   Aaron_ab    5 年前

    eventloop co-routins asyncio

    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()