Skip to content

Add corutine based loop/sleep to documentation #388

@07pepa

Description

@07pepa

Why?

Corutines are cooperative... and their sleep/waiting on event does not actively use up thread

Why this matter...

it blocks (usualy) main thread... and pyhon sometimes uses main thread to do stuff (like handle os signals)
so it may delay handling signals

Example....

blocking handling signals immediately

import schedule
import signal
import time

from threading import Event

terminateCondition = Event()

def loop():
    while not terminateCondition.is_set():
        schedule.run_pending()
        print("runed")
        time.sleep(10)#to increase likeliness that we will interupt during sleep 
    print("loop exited")


def niceKill(signum,frame): #gets handled immediately
    print("killing loop")
    terminateCondition.set()

signal.signal(signal.SIGINT, niceKill) 

loop() #terminate on ctrl+c after sleep expires but handles signal asap

blocking with ocupied main thread

import schedule
import signal

from threading import Event

terminateCondition = Event()

def loop():
    while not terminateCondition.wait(10):#to increase likeliness that we will interupt during wait/sleep
        schedule.run_pending()
        print("runed")
    print("loop exited")


def niceKill(signum,frame): #gets handled after wait expires... wait does not allow for signals to get handled
    print("killing loop")
    terminateCondition.set()

signal.signal(signal.SIGINT, niceKill) 

loop() #terminate on on ctrl+c after sleep expires

non blocking handling signals asap (best option

import asyncio
import schedule
import signal


async def cancelOrWait(event):
    """
    returns true if event is set
    """
    async def waiter():
        await terminateCondition.wait()
    try:
        return await asyncio.wait_for(event.wait(), timeout=10)#to increase likeliness that we will interupt during wait
    except asyncio.TimeoutError:
        return False

def makeKiller(event):
    def killer(signum, frame):
        print("killing loop")
        event.set()
    
    return killer

def setupEvent():
    terminateCondition = asyncio.Event()
    signal.signal(signal.SIGINT,makeKiller(terminateCondition))
    return terminateCondition



async def killableLoop(killEvent):
    while not await cancelOrWait(killEvent):
        print("running")
        schedule.run_pending()
    print("loop exited")

async def main():
   await killableLoop(setupEvent())



asyncio.run(main())#gets terminated imieadly on ctrl+c

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions