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

以下是正常功能的实现:

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循环.我怎样才能让它像正常的一样?也就是说,当它完成时,在给定的延迟时间后调用自己,但不只是在那里放一个循环.

推荐答案

如果您真的想从协程中消除while循环(我不知道为什么您觉得这是必要的;这是做您想做的事情的最自然的方式),您可以使用asyncio.async(或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将在打印后立即退出.

Python-3.x相关问答推荐

使用正确的数据类型时,使用 Cerberus 验证 JSON 架构会引发错误

机器学习实验笔记本的工作区 url

FastAPI - 调用 API 时设置 response_model_exclude

如何将数据框中的每一行转换为具有属性的节点?

所有 Python dunder 方法的列表 - 您需要实现哪些方法才能正确代理对象?

finally 总是在 try 块返回之前运行,那么为什么 finally 块中的更新不会影响 try 块返回的变量的值呢?

在带有 M1 芯片(基于 ARM 的 Apple Silicon)的 Mac 上安装较早版本的 Python(3.8 之前)失败

ValueError:FixedLocator 位置的数量 (5),通常来自对 set_ticks 的调用,与刻度标签的数量 (12) 不匹配

Python 中的 __peg_parser__ 是什么?

python中奇怪的作用域行为

Python 3:在多处理期间捕获警告

Python 无法安装包

NumPy ndarray dtype 的类型提示?

正则表达式找到一对相邻的数字,它们周围有不同的数字

如何在两个方向(向前,向后)上获取每个元素的值的滑动窗口?

Python 3.8 的pip

如何在不使用 @hydra.main() 的情况下获取 Hydra 配置

如何在导入 win32api 时修复“ImportError: DLL load failed”

“with”语句是否支持类型提示?

RuntimeError:输入类型(torch.FloatTensor)和权重类型(torch.cuda.FloatTensor)应该相同