How to interrupt an infinite loop executed by exec in a thread?

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
lgyer
Posts: 29
Joined: Fri Feb 26, 2021 8:09 am

How to interrupt an infinite loop executed by exec in a thread?

Post by lgyer » Tue Mar 09, 2021 6:07 am

Hi,

There are two problems.
One is how to terminate a thread in another thread by using _thread module?
Another problem is how to interrupt an infinite loop executed by exec in a thread? like this:

Code: Select all

import _thread
import time
def task1():
    print('task1 running')
    exec('while True:\n  print("task1 ~~")\n  time.sleep(1)',globals())
def task2():
   print("task2 running")
   while True:
      print("task2 !")
      time.sleep(1)
_thread.start_new_thread(task1,())
_thread.start_new_thread(task2,())
When I use Ctrl+E and Ctrl+D to run this code and use Ctrl+C to stop it, it can't be terminated.
Why can Not I stop it?

User avatar
CmdrDeLiver
Posts: 27
Joined: Thu Dec 05, 2019 6:30 pm

Re: How to interrupt an infinite loop executed by exec in a thread?

Post by CmdrDeLiver » Thu Mar 11, 2021 9:37 pm

Perhaps a flag to indicate it is time to exit?

Code: Select all

import _thread
import time

f_run = True

def task1():
    print('task1 running')
    exec('while f_run:\n  print("task1 ~~")\n  time.sleep(1)',globals())
def task2():
   print("task2 running")
   while f_run:
      print("task2 !")
      time.sleep(1)
_thread.start_new_thread(task1,())
_thread.start_new_thread(task2,())
time.sleep(90)
f_run = False
You could also you an if f_run == False: break to escape at any line that suits you.

lgyer
Posts: 29
Joined: Fri Feb 26, 2021 8:09 am

Re: How to interrupt an infinite loop executed by exec in a thread?

Post by lgyer » Fri Mar 12, 2021 6:30 am

CmdrDeLiver wrote:
Thu Mar 11, 2021 9:37 pm
Perhaps a flag to indicate it is time to exit?

Code: Select all

import _thread
import time

f_run = True

def task1():
    print('task1 running')
    exec('while f_run:\n  print("task1 ~~")\n  time.sleep(1)',globals())
def task2():
   print("task2 running")
   while f_run:
      print("task2 !")
      time.sleep(1)
_thread.start_new_thread(task1,())
_thread.start_new_thread(task2,())
time.sleep(90)
f_run = False
You could also you an if f_run == False: break to escape at any line that suits you.
Hi CmdrDeLiver
Thanks for your reply.
Yes, it can work when the flag to be confirmed. But if the code was very long to execute, how to make it be interrupt immedicately? Is there any way?

User avatar
CmdrDeLiver
Posts: 27
Joined: Thu Dec 05, 2019 6:30 pm

Re: How to interrupt an infinite loop executed by exec in a thread?

Post by CmdrDeLiver » Fri Mar 12, 2021 2:11 pm

Hey Igyer,

This is a job for break and continue! Break exits the loop immediately. Continue forces the loop back to the beginning where the loop condition is evaluated. Both can give you finite control over your exit point.

Code: Select all

while True:
  if f_run == False:
    break
  sleep(1)
  print("still running")
This might be helpful to understanding loop control: https://realpython.com/python-while-loop/

lgyer
Posts: 29
Joined: Fri Feb 26, 2021 8:09 am

Re: How to interrupt an infinite loop executed by exec in a thread?

Post by lgyer » Sat Mar 13, 2021 8:14 am

CmdrDeLiver wrote:
Fri Mar 12, 2021 2:11 pm
Hey Igyer,

This is a job for break and continue! Break exits the loop immediately. Continue forces the loop back to the beginning where the loop condition is evaluated. Both can give you finite control over your exit point.

Code: Select all

while True:
  if f_run == False:
    break
  sleep(1)
  print("still running")
This might be helpful to understanding loop control: https://realpython.com/python-while-loop/
Hi CmdrDeLiver,

Maybe I didn't descript my problem precisely. I know the break can make the loop stopped.
My problem is how to interrupt the loop as quick as possible ,like this:

Code: Select all

while True:
    if f_run == False:
    	break
    balabalabala.......   # these statements could handle some tasks which may consume time very long, maybe 5s - 10s..
    sleep(10)  # like this. So the extreme case is that the f_run has been True, but it still need wait for 10 seconds, instead of exiting immediately.

User avatar
CmdrDeLiver
Posts: 27
Joined: Thu Dec 05, 2019 6:30 pm

Re: How to interrupt an infinite loop executed by exec in a thread?

Post by CmdrDeLiver » Sat Mar 13, 2021 3:56 pm

Have you looked at _thread.exit? I'm unsure how/if it is implemented in micropython as there is zero documentation on the wiki. You might want to go to the source and figure it out.
lgyer wrote:
Sat Mar 13, 2021 8:14 am
My problem is how to interrupt the loop as quick as possible ,like this:
CODE: SELECT ALL

while True:
if f_run == False:
break
balabalabala....... # these statements could handle some tasks which may consume time very long, maybe 5s - 10s..
sleep(10) # like this. So the extreme case is that the f_run has been True, but it still need wait for 10 seconds, instead of exiting immediately.
I see what you mean and there's a simple answer. You can put logic between each statement to break out. That might include turning the sleep statement into something along the lines of

Code: Select all

for i in range(100):
    if f_run == False:
    	break
    sleep(0.1)
Check out _thread.exit() though. It might have the secret sauce you're looking for.

lgyer
Posts: 29
Joined: Fri Feb 26, 2021 8:09 am

Re: How to interrupt an infinite loop executed by exec in a thread?

Post by lgyer » Tue Mar 16, 2021 7:39 am

CmdrDeLiver wrote:
Sat Mar 13, 2021 3:56 pm
Have you looked at _thread.exit? I'm unsure how/if it is implemented in micropython as there is zero documentation on the wiki. You might want to go to the source and figure it out.
lgyer wrote:
Sat Mar 13, 2021 8:14 am
My problem is how to interrupt the loop as quick as possible ,like this:
CODE: SELECT ALL

while True:
if f_run == False:
break
balabalabala....... # these statements could handle some tasks which may consume time very long, maybe 5s - 10s..
sleep(10) # like this. So the extreme case is that the f_run has been True, but it still need wait for 10 seconds, instead of exiting immediately.
I see what you mean and there's a simple answer. You can put logic between each statement to break out. That might include turning the sleep statement into something along the lines of

Code: Select all

for i in range(100):
    if f_run == False:
    	break
    sleep(0.1)
Check out _thread.exit() though. It might have the secret sauce you're looking for.
Okay, thanks a lot. I'll try it. Thanks again.

Post Reply