What I am trying to do:
I am trying to kill a thread that has an infinite loop from a parent process launched. I want the child process to be killed as soon as I change the variable.
What I have done so far:
I have shared a variable with the two threads and once the loop gets the stop signal it stops.
Whats not working:
It is not killing the thread as soon as I send the stop signal
Here is some sample code:
from flask import Flask, flash, redirect, render_template, request, session, abort
import light_control
import logging
import thread
app = Flask(__name__)
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
global stop
stop = False
def loop_rainbow_cycle_successive(name):
global stop
while 1:
if stop == True:
break
light_control.rainbow_cycle_successive()
def loop_rainbow_cycle(name):
global stop
while 1:
if stop == True:
break
light_control.rainbow_cycle()
def loop_rainbow_colors(name):
global stop
while 1:
if stop == True:
break
light_control.rainbow_colors()
RGB = ()
#app.route("/")
def index():
return render_template(
'index.html')
#app.route("/getColor/", methods=['POST'])
def getColor():
RGB = (request.form['r'],request.form['g'],request.form['b'])
light_control.setColor(RGB)
return render_template('index.html')
#app.route("/useFunction/", methods=['POST'])
def useFunction():
global stop
stop = False
func = request.form['function']
if func == "rainbow_cycle_successive":
thread.start_new_thread( loop_rainbow_cycle_successive, ("loop_rainbow_cycle_successive", ))
elif func == "rainbow_cycle":
thread.start_new_thread( loop_rainbow_cycle, ("loop_rainbow_cycle", ))
elif func == "rainbow_colors":
thread.start_new_thread( loop_rainbow_colors, ("loop_rainbow_cycle", ))
elif func == "STOP":
stop = True
return render_template('index.html')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)
You can make it a process and use p.terminate()
code:
from flask import Flask, flash, redirect, render_template, request, session, abort
import sys, os
sys.path.append(os.getcwd() + '/audio-reactive-led-strip/python/')#append entire directory
import logging
import multiprocessing
import light_control, visualization
app = Flask(__name__)
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
global stop
stop = False
p = multiprocessing.Process()
def terminate_process():
global p
if p.is_alive():
p.terminate()
def loop_rainbow_cycle_successive(name):
global stop
while 1:
if stop == True:
break
light_control.rainbow_cycle_successive()
def loop_rainbow_cycle(name):
global stop
while 1:
if stop == True:
break
light_control.rainbow_cycle()
def loop_rainbow_colors(name):
global stop
while 1:
if stop == True:
break
light_control.rainbow_colors()
def loop_visualization(name):
# Initialize LEDs
visualization.led.update()
# Start listening to live audio stream
visualization.microphone.start_stream(visualization.microphone_update)
RGB = ()
#app.route("/")
def index():
return render_template(
'index.html')
#app.route("/getColor/", methods=['POST'])
def getColor():
terminate_process()
RGB = (request.form['r'],request.form['g'],request.form['b'])
light_control.setColor(RGB)
return render_template('index.html')
#app.route("/useFunction/", methods=['POST'])
def useFunction():
global stop
global p
stop = False
func = request.form['function']
if func == "rainbow_cycle_successive":
terminate_process()
p = multiprocessing.Process(target=loop_rainbow_cycle_successive, args=("loop_rainbow_cycle_successive", ))
p.start()
elif func == "rainbow_cycle":
terminate_process()
p = multiprocessing.Process(target=loop_rainbow_cycle, args=("loop_rainbow_cycle", ))
p.start()
elif func == "rainbow_colors":
terminate_process()
p = multiprocessing.Process(target=loop_rainbow_colors, args=("loop_rainbow_cycle", ))
p.start()
elif func == "visualization":
terminate_process()
p = multiprocessing.Process(target=loop_visualization, args=("loop_visualization", ))
p.start()
elif func == "STOP":
stop = True
terminate_process()
return render_template('index.html')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8080)
Related
In my case, I want to hook the keyboard keys that is pressed.
And when I press "0", I want to kill the terminal.
Both functions should work at the same time.
But my code doesn't work. What is wrong with this code?
import keyboard
import asyncio
def sleep(a):
rand1 = random.uniform(0, 0.009)
rand2 = random.uniform(0.01, 0.02)
result = random.uniform(rand1, rand2)
asyncio.sleep(a + result)
async def record_start():
while True:
k = keyboard.read_key()
k = keyboard.read_key()
print(k)
async def record_stop():
while True:
if keyboard.is_pressed('0'):
print('stop')
sleep(1)
exit()
async def main():
await asyncio.gather(
record_stop(),
record_start(),
)
asyncio.run(main())
I tried out using another modules.
And I assume that problem is modules or way to use "while"
your record_start function never gives a chance to any other async code to run.
Introduce an awaiting call in it, like await asyncio.sleep(.01) in it (it may be sleep(0) but I'd advise a larger interval), and things should work.
I just solved this issue.
It doesn't need to use 'asyncio' module.
instead, I run this code with 'threading' module.
from threading import Thread
import os
def thread_1():
while True:
start_time = time.time()
k = keyboard.read_key()
k = keyboard.read_key()
print("sleep(%s)" % round(time.time() - start_time, 3))
print("press('%s')" % k)
def thread_2():
while True:
if keyboard.is_pressed('0'):
print('stop')
pid = os.getpid()
os.kill(pid, 2)
if __name__ == "__main__":
t1 = Thread(target=thread_1)
t2 = Thread(target=thread_2)
print('start')
t1.start()
t2.start()
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
...
I want to stop asynchronous multiprocessing jobs with KeyboardInterrupt. But sometimes hang occurred when call terminate.
from multiprocessing.pool import ThreadPool
import multiprocessing
import time
import queue
import inspect
def worker(index):
print('{}: start'.format(index))
for i in range(5):
time.sleep(1)
print('{}: stop'.format(index))
return index, True
def wrapper(index, stopEvent, qResult):
if stopEvent.is_set() is True:
return index, False
try:
result = worker(index)
except:
print('*' * 50)
return index, False
else:
if result[1] == True:
qResult.put(result)
return result
def watcher(qResult, stopEvent):
cntQ = 0
while True:
try:
result = qResult.get(timeout=10)
qResult.task_done()
except queue.Empty:
if stopEvent.is_set() is True:
break
except KeyboardInterrupt:
stopEvent.set()
else:
cntQ += 1
print(result)
qResult.join()
qResult.close()
print('qResult count:', cntQ)
def main():
stopEvent = multiprocessing.Event()
qResult = multiprocessing.JoinableQueue()
qResult.cancel_join_thread()
watch = multiprocessing.Process(target=watcher, args=(qResult, stopEvent))
watch.start()
pool = ThreadPool()
lsRet = []
for i in range(100000):
try:
ret = pool.apply_async(wrapper, args=(i, stopEvent, qResult))
lsRet.append(ret)
except KeyboardInterrupt:
stopEvent.set()
time.sleep(1)
break
if i+1 % 10 == 0:
time.sleep(2)
cntTotal = len(lsRet)
cntRet = 0
for ret in lsRet:
if stopEvent.is_set():
break
try:
ret.get()
except KeyboardInterrupt:
stopEvent.set()
time.sleep(1)
else:
cntRet += 1
if stopEvent.is_set() is False:
stopEvent.set()
print(inspect.stack()[0][1:4])
if watch.is_alive() is True:
watch.join()
print(inspect.stack()[0][1:4])
pool.terminate() # Why hang??????????
print(inspect.stack()[0][1:4])
pool.join()
print(cntTotal, cntRet)
if __name__ == '__main__':
main()
main() invokes a watcher() thread and many wrapper() threads asynchronously using multiprocessing.pool.Threadpool.
wrapper() calls worker() and put its result to queue.
watcher() watches above queue of results.
If ctrl-c pressed, stopEvent is set.
When stopEvent is set, wrapper() stops calling worker(), and Watcher() indicates queue.Empty and stopEvent and exits loop.
Finally main() calls terminate() of pool.
Sometimes processes done well, but sometimes hang. It's different each time.
You should put the code in try except block and catch a built-in exception KeyboardInterrupt see the example here Capture keyboardinterrupt
I am working on writing a code in raspberry pi using python where i want the user to input the set temperature and fan mode via web page i'm using flask for that and the values are returned successfully but i also want to run a infinite while loop along with the flask app which will compare the set temperature with the current temperature from a sensor.. how do i achieve this without interrupting the flask app?
from flask import Flask
from flask import render_template
from flask import request
from flask import redirect
import time
temp = ""
t = ""
fan_High = 0
fan_Med = 0
fan_Low =0
fanspeed = ""
app = Flask(__name__)
#app.route('/form', methods=['POST'])
def aziz():
global temp ,fanspeed
fanspeedlocal = ''
if request.form['settemp'] != "":
temp = request.form['settemp']
templocal = temp
else:
templocal = temp
if request.form['speed'] == "null":
fanspeedlocal = fanspeed
else:
if request.form['speed'] == "High":
fan_Med = False
fan_Low = False
fan_High = True
fanspeed = "High"
fanspeedlocal = fanspeed
elif request.form['speed'] == "Med":
fan_High = False
fan_Low = False
fan_Med = True
fanspeed = "Medium"
fanspeedlocal = fanspeed
elif request.form['speed'] == "Low":
fan_High = False
fan_Med = False
fan_Low = True
fanspeed = "Low"
fanspeedlocal = fanspeed
print 'Settemp = %s' %temp
print 'fanspeed = %s' %fanspeed
return render_template('Output.html',temp=templocal,currtemp=strct,time=t,fanspeed=fanspeedlocal
#app.route('/')
def start():
global t , fanspeed
t = time.strftime("%H:%M:%S")
return render_template('Start.html',temp=temp,currtemp=strct,time=t,fanspeed=fanspeed)
if __name__ == '__main__':
app.debug = False
app.run(host = '192.168.1.101')
var = 1
while var == 1:
inttemp = int(temp)
if currtemp >= inttemp:
#set GPIO to high
else:
#set GPIO to low
if fanspeed == 'High':
#set GPIO to high
elif fanspeed == 'Med':
#set GPIO to high
elif fanspeed == 'LOW':
#set GPIO to high
time.sleep(10)
I would just use cron. You could use a simple script that looks something like this:
#!/usr/bin/python3
# or python, if that's your thing
import requests
def get_sensor_data():
'''Presumably you know what actually goes here.'''
return {'temperature': 5, 'fan speed': 'no, three, sir'}
requests.post('http://example.com/update?api_key=12345', data=get_sensor_data())
Then just setup cron to run it every 60s or less. Now your Flask app just gets requests from your script that updates the data, while your page updates.
Alternatively, you could just setup a Flask #app.before_request decorator that will just request the necessary data and attach it to the special g object.
If it's quick (<250ms) to read the data, I'd probably do the latter. If it takes more than 250ms, then I'd probably make cron do it.
I think, you just input the while command inside the:
#app.route('/')
def start():
or in some place which you like
Thanks to #user5402 for the previous solution.
I am trying to handle multiple messages that are queued up. Here is the code:
import sys
import socket
from multiprocessing import Process, Queue
UDP_ADDR = ("", 13000)
def send(m):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(m, UDP_ADDR)
def receive(q):
buf = 1024
Sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Sock.bind(UDP_ADDR)
while True:
(data, addr) = Sock.recvfrom(buf)
q.put(data)
In the client function I want to handle multiple messages, that have knock on affects.
def client():
q = Queue()
r = Process(target = receive, args=(q,))
r.start()
print "client loop started"
while True:
m = q.get()
print "got:", m
while m == "start":
print "started"
z = q.get()
if z == "stop":
return
print "loop ended"
r.terminate()
So when start is sent, it then goes into a while loop that is infinitely printing "started", and waiting for the stop message to come through. The above client code does not work.
Here is the code to start the function:
if __name__ == '__main__':
args = sys.argv
if len(args) > 1:
send(args[1])
else:
client()
You can write the client loop like this:
print "client loop started"
while True:
m = q.get()
print "waiting for start, got:", m
if m == "start":
while True:
try:
m = q.get(False)
except:
m = None
print "waiting for stop, got:", m
if m == "stop":
break
Based on your comments, this would be a better approach:
import sys
import socket
import Queue as Q
import time
from multiprocessing import Process, Queue
UDP_ADDR = ("", 13000)
def send(m):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(m, UDP_ADDR)
def receive(q):
buf = 1024
Sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Sock.bind(UDP_ADDR)
while True:
(data, addr) = Sock.recvfrom(buf)
q.put(data)
def doit():
# ... what the processing thread will do ...
while True:
print "sleeping..."
time.sleep(3)
def client():
q = Queue()
r = Process(target = receive, args=(q,))
r.start()
print "client loop started"
t = None # the processing thread
while True:
m = q.get()
if m == "start":
if t:
print "processing thread already started"
else:
t = Process(target = doit)
t.start()
print "processing thread started"
elif m == "stop":
if t:
t.terminate()
t = None
print "processing thread stopped"
else:
print "processing thread not running"
elif m == "quit":
print "shutting down"
if t:
t.terminate()
t = None # play it safe
break
else:
print "huh?"
r.terminate()
if __name__ == '__main__':
args = sys.argv
if len(args) > 1:
send(args[1])
else:
client()