Python 中父函数的 Yield?

问题描述 投票:0回答:2

我有一个 Python 音乐库,它涉及一个时钟系统。目前,它们是通过不同的线程实现的,这些线程使用事件和锁等来保持一切同步。但事实是,我希望它是有效的单线程。

时钟的当前语法是您可以像这样分叉函数:

def some_musical_process():
    play_a_note()
    wait(2)
    play_another_note()
    wait(1.5)
    ...etc...

fork(some_musical_process)

当一个函数被 fork 时,它被建立在它自己的线程上。 wait 函数导致进程的执行停止并等待信号在 2 个节拍后唤醒。问题是,由于这些函数中的每一个都是一个不同的线程,因此在正确的时间停止和启动它们有点像噩梦。

我一直觉得这更适合使用生成器函数;沿着这些方向的东西:

import random
import time


def yielding_routine():
    while True:
        print("hello")
        yield random.choice([0.5, 1.0])



# Scheduler
yr = yielding_routine()
delay = next(yr)
while True:
    time.sleep(delay)
    delay = next(yr)

问题是,我不想更改API。我想保持用户调用“wait”而不是 yield,部分是为了向后兼容,部分是因为有几个专门的等待函数,如“wait_for_children_to_finish()”和类似的东西。我真正想要的是这样的:

def yielding_routine():
    while True:
        print("hello")
        wait(random.choice([0.5, 1.0]))


def wait(dur):
    (((somehow cause the parent to yield dur)))

wait
函数以某种方式在父生成器函数中产生。 Python 有什么办法可以做到这一点吗?甚至是用“eval”之类的东西?实际上我想要的是一个宏,我不确定是否有好的方法可以在 Python 中获得这种功能。

或者有没有我没有考虑过的替代方法?

非常感谢!

python macros yield
2个回答
0
投票

我建的曲库用实际时间来解决调度问题。这是我为我解决这个问题的实际方法:

def wait_for_the_future(target_time):
    """ If target_time is in future, sleep 'til then. """
    time_remaining = target_time - datetime.datetime.now()
    if time_remaining > datetime.timedelta(seconds=.000001):
        time.sleep(max(0, time_remaining.total_seconds() - .000001))

如果采用这种方法,困难的部分是将音乐事件及时转换为时刻的调度数学。


0
投票

您可能想使用

asyncio
模块来定义协程。这需要对语法进行一些小的更改,但在其他方面保持您的 API 不变。

import asyncio
from asyncio import sleep as wait


async def yielding_routine():
    while True:
        print("hello")
        await wait(random.choice([0.5, 1.0]))

yr = yielding_routine()

asyncio.run(yr)

您可能还想阅读有关

asyncio
模块的更多信息,以了解如何使用
async def
定义的协程。

© www.soinside.com 2019 - 2024. All rights reserved.