How to stop a function from another function? - python

TOKEN = 'token'
bot = telebot.TeleBot(TOKEN)
def main():
for i in range(0,100):
print(i)
#bot.message_handler(commands=['start'])
def start(message):
main()
#bot.message_handler(commands=['stop'])
def stopfunc(message):
#how to stop the function main() ?
while True:
bot.polling()

Add stop flag :
Add logic to main function : when stop flag is True, the main function should return
In stopfunc set the stop flag is True
stop = False
def main():
global stop
for i in range(0,100):
if stop:
break
print(i)
#bot.message_handler(commands=['stop'])
def stopfunc(message):
global stop
stop = True
...

Related

How to use a changing variable value in a while loop | Python

I have a python program and a server that written with flask.
The thing I want to do is send a request to the server about is there any new order.
Server returns a JSON file as response if there is an active: True value in JSON should run my script. While script is running my program should continue to send request because while program running active value can be change to False. If active: False script should stop but I have to continue to send request to the server for checking the new orders.
I am adding an example below. If you have any question marks in your mind please let me know:
import time
def read_active_data():
pass
def my_func(active):
while True:
print("my_func is active")
if active == False:
break
count=0
active=False
while True:
if count%10==0:
active= read_active_data()
if active==True:
my_func(active)
time.sleep(1)
count+=1
I solved it like this:
from threading import Thread
import time
count=0
active= False
def set_active():
global active
global count
while True:
if count%10==0:
if active:
active=False
print("Inactive")
else:
active=True
print("Active")
time.sleep(1)
def kronos():
global count
while True:
time.sleep(1)
count+=1
print("Count is: ",count)
def execute():
global active
while True:
if active:
print("Executing")
else :
print("Not executing")
time.sleep(1)
if __name__ == '__main__':
t1 = Thread(target=set_active)
t2 = Thread(target=kronos)
t3 = Thread(target=execute)
t1.start()
t2.start()
t3.start()

How can I trigger an event twice in Python with multiprocessing

So I wrote simple test code and I'm trying to execute event twice, but it only works once. After turn_left_e.set() I clear inner flag with turn_left_e.clear() (I also check it in code) and trying execute event second time, but it won't start. Here is my code:
import time
from multiprocessing import Event, Process
def check_light_dir(turn_left_e, turn_right_e):
while True:
time.sleep(2)
var = random.randint(1, 10)
print(f"var: {var}")
if var < 5:
print(f"turn_left_e before set(): {turn_left_e.is_set()}")
turn_left_e.set()
else:
print(f"turn_right_e before set(): {turn_right_e.is_set()}")
turn_right_e.set()
def turn_left(turn_left_e):
turn_left_e.wait()
print(f"turn_left_e after set(): {turn_left_e.is_set()}")
print("Turning servo left")
turn_left_e.clear()
print(f"turn_left_e after clear(): {turn_left_e.is_set()}")
def turn_right(turn_right_e):
turn_right_e.wait()
print(f"turn_right_e after set(): {turn_right_e.is_set()}")
print("Turning servo right")
turn_right_e.clear()
print(f"turn_right_e after clear(): {turn_right_e.is_set()}")
def test():
turn_right_e = Event()
turn_left_e = Event()
check_light_dir_p = Process(target=check_light_dir, args=(turn_left_e, turn_right_e,))
turn_right_p = Process(target=turn_right, args=(turn_right_e,))
turn_left_p = Process(target=turn_left, args=(turn_left_e,))
check_light_dir_p.start()
turn_left_p.start()
turn_right_p.start()
check_light_dir_p.join()
turn_right_p.join()
turn_left_p.join()
if __name__ == "__main__":
print("start")
test()
print("stop")
Output:
start
var: 4
turn_left_e before set(): False
turn_left_e after set(): True
Turning servo left
turn_left_e after clear(): False
var: 10
turn_right_e before set(): False
turn_right_e after set(): True
Turning servo right
turn_right_e after clear(): False
var: 9
turn_right_e before set(): False
var: 10
turn_right_e before set(): True
var: 2
turn_left_e before set(): False
var: 5
turn_right_e before set(): True
Process finished with exit code -1
So 1st and 2nd iterations servo moved. Funny part starts here: in 3rd iteration "before set()" was false and in 4th "before set()" was true! It seems to trigger event but didn't jump into it - there never was 2nd print "servo moved ..." and inner flags are infinitely set to True.
I don't understand why does it happens. I clear() events, so they should trigger as long as conditions is satisfied right?
The issue is, that functions turn_left and turn_right exits after first Event set and their processes end. Put while True: inside them:
...
def turn_left(turn_left_e):
while True: # <--------
turn_left_e.wait()
print(f"turn_left_e after set(): {turn_left_e.is_set()}")
print("Turning servo left")
turn_left_e.clear()
print(f"turn_left_e after clear(): {turn_left_e.is_set()}")
def turn_right(turn_right_e):
while True: # <--------
turn_right_e.wait()
print(f"turn_right_e after set(): {turn_right_e.is_set()}")
print("Turning servo right")
turn_right_e.clear()
print(f"turn_right_e after clear(): {turn_right_e.is_set()}")
...

Stop While Loop mid execution in python

I am trying to stop a while loop mid execution, if I reverse the value of 'runWhile' mid execution it simply waits until it's over.
Problem: I need it to stop immediately whenever I press f10 on the keyboard.
from pynput import keyboard
import threading
import datetime, time
def exec():
while runWhile:
print("There I go")
time.sleep(3)
print("I overtaken")
time.sleep(3)
print("You cant stop me until I finish")
def on_press(key):
global runWhile # inform function to assign (`=`) to external/global `running` instead of creating local `running`
if key == keyboard.Key.f5:
runWhile = True
t = threading.Thread(target=exec)
t.start()
if key == keyboard.Key.f10:
# to stop loop in thread
print("loading STOPPED", datetime.datetime.now()) #, end='\r')
runWhile = False
if key == keyboard.Key.f11:
# stop listener
print("listener TERMINATED", datetime.datetime.now()) #, end='\r')
return False
#--- main ---
with keyboard.Listener(on_press=on_press) as listener:
listener.join()
Im using pynput, docs here
based on #furas code
Here is a solution I made. I created my own delay function as follows:
def delay(amount): #delay time in seconds
for i in range(int(amount*60)):
time.sleep(0.01)
if runWhile == False:
return True
break
You would replace your delay(3) with
if delay(3):
break
This would wait 3 seconds, however if during that time, runWhile was false, it will break out of the loop. Your code would look like this:
from pynput import keyboard
import threading
import datetime, time
def delay(amount): #delay time in seconds
for i in range(int(amount*60)):
time.sleep(0.01)
if runWhile == False:
return True
break
def exec():
while runWhile:
print("There I go")
if delay(3):
break
print("I overtaken")
if delay(3):
break
print("You cant stop me until I finish")
def on_press(key):
global runWhile # inform function to assign (`=`) to external/global `running` instead of creating local `running`
if key == keyboard.Key.f5:
runWhile = True
t = threading.Thread(target=exec)
t.start()
if key == keyboard.Key.f10:
# to stop loop in thread
print("loading STOPPED", datetime.datetime.now()) #, end='\r')
runWhile = False
if key == keyboard.Key.f11:
# stop listener
print("listener TERMINATED", datetime.datetime.now()) #, end='\r')
return False
#--- main ---
with keyboard.Listener(on_press=on_press) as listener:
listener.join()

Why my loop stops executing only if I input false 2 times?

Why does my code execute like this? I want to break loop when user inputs "Q", but it stops only when I input "Q" 2 times. Sometimes it doesn't even stop after 2 "Q"s. It's purely random.
code
import json
class Kasa:
def __init__(self):
self._running = True
while self._running:
print(self._running)
try:
with open('save.json') as json_file:
DATA = json.load(json_file)
CHOICE = input()
self._running = self.handleEvent(CHOICE)
except IOError:
CHOICE = input()
self._running = self.handleEvent(CHOICE)
def handleEvent(self, event):
if event == 'C':
pass
elif event == 'Q':
return False
else:
return True
if __name__ == "__main__":
Kasa().__init__()
exec output
>>>python file.py
True
True
True
True
True
Q
True
True
True
Q
#script stopped executing here
No need to explicitly call init,
calling Kasa() class will automatically call init
if __name__ == "__main__":
Kasa()
I would rather suggest to write the logic outside init in a seperate method

Python Tkinter, Stop a threading function

I'm currently developing a GUI for a 3D printer and I'm having a problem of how to stop a threading function. I want to be able to click a button that has another function within my GUI that will stop the threading function from sending strings of G-code across the serial port. Currently the function has threading incorporated to allow other functions to be triggered during printing. I would greatly appreciate some advice on how I would incorporate this stop feature.
Below is the function that opens a G-code file and sends each line across the serial port.
def printFile():
def callback():
f = open(entryBox2.get(), 'r');
for line in f:
l = line.strip('\r')
ser.write("<" + l + ">")
while True:
response = ser.read()
if (response == 'a'):
break
t = threading.Thread(target=callback)
t.start()
Threads cannot be stopped, they have to stop themselves. So you need to send a signal to the thread that it's time to stop. This is usually done with an Event.
stop_event = threading.Event()
def callback():
f = open(entryBox2.get(), 'r');
for line in f:
l = line.strip('\r')
ser.write("<" + l + ">")
while True:
response = ser.read()
if (response == 'a'):
break
if stop_event.is_set():
break
t = threading.Thread(target=callback)
t.start()
Now if you set the event elsewhere in your code:
stop_event.set()
The thread will notice that, break the loop and die.
Use a global variable as a condition for the thread to stop.
send_gcode = True
def printFile():
def print_thread():
f = open(entryBox2.get(), 'r');
for line in f:
if not send_gcode:
break
l = line.strip('\r')
ser.write("<" + l + ">")
while True:
response = ser.read()
if (response == 'a'):
break
t = threading.Thread(target=print_thread)
send_gcode = True
t.start()
The thread will run until send_gcode is set to False (by e.g. a callback for a button:
def stop_callback(event):
global send_gcode
send_gcode = False

Categories

Resources