我对python的 asyncio 非常熟悉,它是python中的异步编程,协同例程等。 我希望能够使用自己定制的 eventloop 执行多个协同例程。
我很好奇我是否可以编写自己的 eventloop 而不完全导入 asyncio
答案 0 :(得分:2)
我希望能够使用自己定制的事件循环执行多个协同例程。
异步事件循环经过了充分的测试,可以轻松扩展以确认非异步事件。如果您描述了实际的用例,则可能会更容易获得帮助。但是,如果您的目标是学习有关异步编程和协程的信息,请继续阅读。
我很好奇我是否可以编写我自己的事件循环而无需完全导入asyncio
这绝对有可能-毕竟asyncio本身只是一个库-但要使事件循环有用,还需要一些工作。请参阅David Beazley的this excellent talk,其中他演示了如何在现场观众面前编写事件循环。 (David并不会使用较旧的yield from
语法-await
的工作方式完全相同。)
答案 1 :(得分:0)
好,所以我在某个地方找到了一个示例(对不起,不记得在哪里,没有链接),并做了一些修改。
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()