如何创建一个永远运行滚动协同程序的事件循环?

2024-05-20 20:21:28 发布

您现在位置:Python中文网/ 问答频道 /正文

为了防止上下文切换,我想创建一个大循环来服务于网络连接和一些例程。

以下是正常功能的实现:

import asyncio
import time


def hello_world(loop):
    print('Hello World')
    loop.call_later(1, hello_world, loop)

def good_evening(loop):
    print('Good Evening')
    loop.call_later(1, good_evening, loop)

print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()

print('step: loop.call_soon(hello_world, loop)')
loop.call_soon(hello_world, loop)
print('step: loop.call_soon(good_evening, loop)')
loop.call_soon(good_evening, loop)

try:
    # Blocking call interrupted by loop.stop()
    print('step: loop.run_forever()')
    loop.run_forever()
except keyboardInterrupt:
    pass
finally:
    print('step: loop.close()')
    loop.close()

以下是协作的实现:

import asyncio


@asyncio.coroutine
def hello_world():
    while True:
        yield from asyncio.sleep(1)
        print('Hello World')

@asyncio.coroutine
def good_evening():
    while True:
        yield from asyncio.sleep(1)
        print('Good Evening')

print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()
try:
    print('step: loop.run_until_complete()')
    loop.run_until_complete(asyncio.wait([
        hello_world(),
        good_evening()
    ]))
except KeyboardInterrupt:
    pass
finally:
    print('step: loop.close()')
    loop.close()

而混血儿:

import asyncio
import time


def hello_world(loop):
    print('Hello World')
    loop.call_later(1, hello_world, loop)

def good_evening(loop):
    print('Good Evening')
    loop.call_later(1, good_evening, loop)

@asyncio.coroutine
def hello_world_coroutine():
    while True:
        yield from asyncio.sleep(1)
        print('Hello World Coroutine')

@asyncio.coroutine
def good_evening_coroutine():
    while True:
        yield from asyncio.sleep(1)
        print('Good Evening Coroutine')

print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()

print('step: loop.call_soon(hello_world, loop)')
loop.call_soon(hello_world, loop)
print('step: loop.call_soon(good_evening, loop)')
loop.call_soon(good_evening, loop)
print('step: asyncio.async(hello_world_coroutine)')
asyncio.async(hello_world_coroutine())
print('step: asyncio.async(good_evening_coroutine)')
asyncio.async(good_evening_coroutine())

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass
finally:
    print('step: loop.close()')
    loop.close()

如您所见,每个协程函数都有一个while循环。我怎样才能让它像正常的一样?一、 完成后,在给定的延迟时间后调用自己,但不要只是在那里放置一个循环。


Tags: loopeventasynciohelloworldclosegetdef
3条回答
import asyncio


@asyncio.coroutine
def hello_world_coroutine():
    yield from asyncio.sleep(1)
    print('Hello World Coroutine')
    yield from hello_world_coroutine()

@asyncio.coroutine
def good_evening_coroutine():
    yield from asyncio.sleep(1)
    print('Good Evening Coroutine')
    yield from good_evening_coroutine()

print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()
try:
    print('step: loop.run_until_complete()')
    loop.run_until_complete(asyncio.wait([
        hello_world_coroutine(),
        good_evening_coroutine()
    ]))
except KeyboardInterrupt:
    pass
finally:
    print('step: loop.close()')
    loop.close()

升级版

此代码将达到最大递归深度。可能是因为Python没有尾部调用优化。把代码留在这里作为一个错误的例子。

如果您真的想从协程中消除while循环(我不确定为什么您认为这是必要的;这是您尝试执行的最自然的方法),可以使用^{}(或者Python 3.4.4+上的asyncio.ensure_future)来安排协程在下一个事件循环迭代中再次运行:

import asyncio

@asyncio.coroutine
def hello_world():
    yield from asyncio.sleep(1)
    print('Hello World')
    asyncio.async(hello_world())

@asyncio.coroutine
def good_evening():
    yield from asyncio.sleep(1)
    print('Good Evening')
    asyncio.async(good_evening())

print('step: asyncio.get_event_loop()')
loop = asyncio.get_event_loop()
try:
    print('step: loop.run_until_complete()')
    asyncio.async(hello_world())
    asyncio.async(good_evening())
    loop.run_forever()
except KeyboardInterrupt:
    pass
finally:
    print('step: loop.close()')
    loop.close()

请注意,如果这样做,则必须切换回使用loop.run_forever(),因为hello_world/good_evening将在打印后立即退出。

# asyncio_coroutine_forever.py

import asyncio

async def hello_world():

    await asyncio.sleep(1)
    print('Hello World')
    await good_evening()


async def good_evening():

    await asyncio.sleep(1)
    print('Good Evening')
    await hello_world()


loop = asyncio.get_event_loop()

try:

    loop.run_until_complete(hello_world())
    loop.run_until_complete(good_evening())
    loop.run_forever()

finally:

    print('closing event loop')
    loop.close()

相关问题 更多 >