microbit-foundation / micropython-microbit-v2

Temporary home for MicroPython for micro:bit v2 as we stablise it before pushing upstream
MIT License
42 stars 23 forks source link

Should `run_every` continue running if the REPL was triggered? #90

Closed microbit-carlos closed 2 years ago

microbit-carlos commented 2 years ago

If we have a function running on a schedule with the @run_every decorator and then the user enters the REPL via serial the function continue running as scheduled.

If this function prints something to the serial output it might interfere with tools using the REPL to interact with MicroPython to flash the micro:bit or run other actions. So we should probably stop these functions from running?

dpgeorge commented 2 years ago

I think they should continue to function at the REPL. That makes it very easy to explore @run_every and see how it works.

It won't interfere with tools because they should be using raw REPL combined with soft-reset, which will make sure the device restarts without any main.py being executed.

microbit-carlos commented 2 years ago

You are right, I forgot that the tooling uses soft-reset, so it doesn't affect things like microFS or Mu. I also completely agree that it'll be useful to have @run_every running in the REPL as a way to explore how it works.

The only thing I still find a bit user hostile is that if there is a main.py like this one, where @run_every schedules a function that prints something to the serial continuously, then it makes the REPL unusable, as anything you type is interweave with the serial output:

from microbit import *
import log

log.set_mirroring(True)

@run_every(ms=250)
def log_temp():
    log.add(temp=temperature())

Even if the time is set to a couple of seconds it can be quite disruptive to have some serial data outputted halfway through typing your code.

Would there be any disadvantage to cancelling any running scheduled call, but still let users scheduled new calls in the REPL?

dpgeorge commented 2 years ago

Would there be any disadvantage to cancelling any running scheduled call

Do you mean, stop all existing run-every's when the main.py finishes/exits? That could work, and shouldn't be hard to implement. That might make good conceptual sense as well: when your main.py finishes so do all your run-every callbacks. Although, that would mean that one can't use main.py to set up run-every's that are intended to continue at the REPL.

microbit-carlos commented 2 years ago

Yes, that's what I meant.

Although, that would mean that one can't use main.py to set up run-every's that are intended to continue at the REPL.

I'm struggling to think of a use case for having it still running in the REPL, but I'm sure somebody will come up with something once it's out 😅 If somebody needs to run a function with run_every in the REPL they could still use the decorator as a function, as soon as they enter the REPL no? run_every(foo, s=1)

dpgeorge commented 2 years ago

If somebody needs to run a function with run_every in the REPL they could still use the decorator as a function, as soon as they enter the REPL no? run_every(foo, s=1)

If foo was decorated with @run_every then foo is a <run_every> object, not a function. So they'd need to declare foo as a plain function to be able to use it at the REPL.

dpgeorge commented 2 years ago

Fixed by 52126a46e1519b9b60f3276ffcb80154c7da0cd5: when the main program drops to the REPL, all existing run_every are cancelled.