Running a continous while loop in python along with Flask app - python

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

Related

Flask project works locally but not in Heroku [duplicate]

This question already has answers here:
Are global variables thread-safe in Flask? How do I share data between requests?
(4 answers)
Closed 2 years ago.
I made this simple chat bot in Python and Flask. It works perfectly when I run it in a local server but I uploaded it to Heroku (my first time uploading) and some options only work sometimes.
In the above image, entering 3 should prompt the app to ask user for a city name but it doesn't most of the times.
#imports
import requests
from flask import Flask, render_template, request
app = Flask(__name__)
import random
newsApiKey = 'c0f976e7caac4b608d84c4546e0b892c'
isGreeted = False
isThree = False
def getRequest(location):
global newsApiKey
url = "http://newsapi.org/v2/everything?q={} AND +corona AND english&qInTitle=+corona&language=en&from=2020-03-25&sortBy=relevancy&apiKey={}".format(location,newsApiKey)
r = requests.get(url)
return r
def getGreeting():
greets = ['Hello there General Kenobi!', 'Hi there!', 'Hi, how are you?']
return random.choice(greets)
#define app routes
#app.route("/")
def index():
return render_template("index.html")
#app.route("/get")
#function for the bot response
def get_bot_response():
global isGreeted
global isThree
userText = request.args.get('msg')
# return str(englishBot.get_response(userText))
responseMessage = ""
if userText in ['Hi!', 'Hello!', 'Hi'] and isGreeted == False:
responseMessage = getGreeting() + "\n\nChoose an option from below menu:\n\n1 - What is Covid-19?\n\n2 - What are the symptoms of Covid-19?\n\n3 - Local news about Covid-19\n\n4 - What should I do?"
isGreeted = True
elif userText in ['1','2','3','4'] and isGreeted:
if userText == '1':
responseMessage = "Coronavirus disease (COVID-19) is an infectious disease caused by a newly discovered coronavirus."
elif userText == '2':
responseMessage = "Common symptoms include fever, tiredness, dry cough. Other symptoms include shortness of breath, aches and pains, sore throat, diarrhoea, runny nose. People with mild symptoms should try self isolating and others should seek medical attention."
elif userText == '3' and isThree == False:
responseMessage = 'Enter your city name'
isThree = True
elif userText == '4':
responseMessage = 'Stay at home. If you plan to go outside, avoid using public transportation. Seek medical attention if you have trouble breathing, pain in chest, bluish lips. Cover your face with an N95 mask. Clean your hands often.'
elif isThree:
r = getRequest(userText).json()
# print(r)
isThree = False
counter = 0
for article in r['articles']:
if counter != 3:
responseMessage += article['title'] + '\n' + article['description'] + '\n\n'
counter = counter + 1
else:
break
return responseMessage
if __name__ == "__main__":
app.run()
Does it have anything to do with the way I handle responses? Or the fact I am using global variables? If yes, what is the better way to do this? Thank you in advance.
I would suggest using flask-socketio for realtime comunication especially for chat. It's a wrapper for socket-io
https://flask-socketio.readthedocs.io/en/latest/
In python
import flask
from flask_socketio import SocketIO
app = Flask(__name__)
socketio = SocketIO(app)
#socketio.on('message')
def handle_message(data):
#handle message
if __name__ == "__main__":
socketio.run(app)
On client
var socket = io();
socket.emit('message', { "msg": "something"});
Also to check what's going on ur heroku server use this
heroku logs --tail

Why my H bridge keep burning when i activate only the b motors (or only the a)

i try to build a very small rc car using 4 motors with my raspberry using th gpio pin but it only work when i set all the motors to turn, when i only set one motors to turn it blow up
My build: https://i.imgur.com/4mza4fQ.png
I tried to use two h bridge to use only the A side with one and only the A side with the other when i press my key.up to activate all of them it work perfectly same for key.down it work perfect. but when i press my key right or left the motors turn for a demie seconds and stop but the led on the h bridge keep lighting normal but i think its because there is 12v.
import RPi.GPIO as GPIO
import time
import json
from flask import Flask
from flask import request
import sys
app = Flask(__name__)
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
MotorgauchePlus = 16
MotorgaucheMoin = 18
MotordroitePlus = 22
MotordroiteMoin = 24
GPIO.setup(MotorgauchePlus,GPIO.OUT)
GPIO.setup(MotorgaucheMoin,GPIO.OUT)
GPIO.setup(MotordroiteMoin,GPIO.OUT)
GPIO.setup(MotordroitePlus,GPIO.OUT)
def Avant():
print ("Going forwards")
GPIO.output(MotorgauchePlus,GPIO.HIGH)//IT WORK
GPIO.output(MotorgaucheMoin,GPIO.LOW)
GPIO.output(MotordroitePlus,GPIO.HIGH)
GPIO.output(MotordroiteMoin,GPIO.LOW)
def Arriere():
print ("Going backwards")
GPIO.output(MotorgauchePlus,GPIO.LOW)//IT WORK
GPIO.output(MotorgaucheMoin,GPIO.HIGH)
GPIO.output(MotordroitePlus,GPIO.LOW)
GPIO.output(MotordroiteMoin,GPIO.HIGH)
def Gauche():
print ("Left")
GPIO.output(MotorgauchePlus,GPIO.LOW)//ai caramba
GPIO.output(MotorgaucheMoin,GPIO.HIGH)
GPIO.output(MotordroitePlus,GPIO.LOW)
GPIO.output(MotordroiteMoin,GPIO.LOW)
def Droite():
print ("Right")
GPIO.output(MotorgauchePlus,GPIO.LOW)//same
GPIO.output(MotorgaucheMoin,GPIO.LOW)
GPIO.output(MotordroitePlus,GPIO.HIGH)
GPIO.output(MotordroiteMoin,GPIO.LOW)
def Stop():
GPIO.output(MotorgauchePlus,GPIO.LOW)//That work
GPIO.output(MotorgaucheMoin,GPIO.LOW)
GPIO.output(MotordroitePlus,GPIO.LOW)
GPIO.output(MotordroiteMoin,GPIO.LOW)
#app.route('/', methods=['POST'])
def AvanOuArriere():
Alors = request.form['Alors']
if Alors == "Quite":
GPIO.output(MotorgauchePlus,GPIO.LOW)
GPIO.output(MotorgaucheMoin,GPIO.LOW)
GPIO.output(MotordroitePlus,GPIO.LOW)
GPIO.output(MotordroiteMoin,GPIO.LOW)
GPIO.cleanup()
sys.exit()
return("oklm")
elif Alors == "Avant":
Avant()
elif Alors == "Gauche":
Gauche()
elif Alors == "Droite":
Droite()
elif Alors == "Arriere":
Arriere()
elif Alors == "Stop":
Stop()
else:
pass
return("oklm")
try:
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
except Exception as e:
print(e)
GPIO.output(MotorgauchePlus,GPIO.LOW)
GPIO.output(MotorgaucheMoin,GPIO.LOW)
GPIO.output(MotordroitePlus,GPIO.LOW)
GPIO.output(MotordroiteMoin,GPIO.LOW)
GPIO.cleanup()
I'm completly lost because to activate a motor i only need to set one pin to HIGH and another to LOW, thats what i do for activate all of them and it work !
Maybe its because i set MotordroitePlus to LOW and MotordroiteMoin to also LOW but its in the Stop function and it work also like it should do so i need your help because im missing something.

How to attach a method to the event of closing down the python application?

I need assistance on the following problem that I am facing.
I have a Tkinter UI which have 3 buttons (Register, Lock the folders and unlock the folders). There is a cross button on the top right corner as in all the applications. Refer to the following snapshot.
So the idea is that when user unlocks his folder through this UI, and then press the cross button, that folder and all the folder's content which might have been opened by the user, must be closed down.
Below is the Code for closing down the folders.
def lockFolder_crossButton():
if userName.get()!='':
answer_folder = getFolderName()
#####check if the folder has already been locked or not!!!!*********
if os.path.exists('./secretFolder/'+userName.get()):
LockFolder.lockFolders(userName.get(), answer_folder)
global timer_active
timer_active = 'no'
window.destroy()
The above code is present in a class "openApplication.py" which is started when this application runs.
The following code of class Facelock.launch.pyw imports this class.
#!python2.7
import sys, os
scriptdir, script = os.path.split(__file__)
pkgdir = os.path.join(scriptdir, 'pkgs')
sys.path.insert(0, pkgdir)
os.environ['PYTHONPATH'] = pkgdir + os.pathsep + os.environ.get('PYTHONPATH', '')
# APPDATA should always be set, but in case it isn't, try user home
# If none of APPDATA, HOME, USERPROFILE or HOMEPATH are set, this will fail.
appdata = os.environ.get('APPDATA', None) or os.path.expanduser('~')
if 'pythonw' in sys.executable:
# Running with no console - send all stdstream output to a file.
kw = {'errors': 'replace'} if (sys.version_info[0] >= 3) else {}
sys.stdout = sys.stderr = open(os.path.join(appdata, script+'.log'), 'w', **kw)
else:
# In a console. But if the console was started just for this program, it
# will close as soon as we exit, so write the traceback to a file as well.
def excepthook(etype, value, tb):
"Write unhandled exceptions to a file and to stderr."
import traceback
traceback.print_exception(etype, value, tb)
with open(os.path.join(appdata, script+'.log'), 'w') as f:
traceback.print_exception(etype, value, tb, file=f)
sys.excepthook = excepthook
if __name__ == '__main__':
from openApplication import self
self()
The following code is the snapshot related to the cross button of the UI window and the method calling after that button is pressed.
window = Tk()
window.title("FaceLock")
window.geometry('800x800')
####some piece of code
window.protocol('WM_DELETE_WINDOW', lockFolder_crossButton)
window.mainloop()
The following is the error that I am facing.
So is there any idea what is the issue here?
And how do you suggest to approach the problem?
Below is the code for openApplication.py
from Tkinter import *
import detector as dt
import os
import dataSetGenerator as generate
import trainData as train
import storeDictionary as save
from subprocess import Popen
import random
import pickle
import CheckFace as checkFace
import createAndHide as CreateFolder
from threading import Timer
import LockFolder, UnlockFolder
window = Tk()
window.title("FaceLock")
window.geometry('800x800')
empCode=StringVar()
userName=StringVar()
duration=StringVar()
errorLabel=Label(text="")
remaining=10
timer_active='no'
sub_folder='no'
locked=False
usertimer=StringVar()
timerLabel=Label(text="")
timerlabelcountdown=Label(text="")
def saveDictionary():
errorLabel.config(text='')
if userName.get() == '':
errorLabel.config(text="User name cant be left blank")
return
if empCode.get() == '':
errorLabel.config(text=" Employee code Cant be left blank")
return
try:
val = int(empCode.get())
except ValueError:
errorLabel.config(text="Enter a valid employee ID")
return
if duration.get() == '':
errorLabel.config(text="Duration cant be left blank")
return
try:
val = int(duration.get())
except ValueError:
errorLabel.config(text="Enter a valid Duration")
return
if int(duration.get())<1 or int(duration.get())>61:
errorLabel.config(text="Enter between 0 and 60 min")
return
if(save.findName(empCode.get())!='not' or save.findEmpCode(userName.get())!='not'):
errorLabel.config(text="User with this employee id or user name has already been registered")
return
flag=checkFace.checkFace()
if(flag==False):
errorLabel.config(text="This face is already a known face")
return
range_start = 10 ** (4 - 1)
range_end = (10 ** 4 ) - 1
rndmnumber= str(random.randint(range_start, range_end))
if len(duration.get()) == 1:
foldername=rndmnumber+'0'+duration.get()+empCode.get()
print "employee code ="+empCode.get()+" username for this is "+userName.get()
else:
foldername = rndmnumber +duration.get() + empCode.get()
dict={empCode.get():str(userName.get())}
save.store(dict)
dict2={userName.get():foldername}
save.storeFolder(dict2)
generateData()
trainData()
def recogniseFace():
flag=dt.detector()
print flag
window.destroy
print empCode.get()
def generateData():
generate.generateDataSet(empCode.get())
def trainData():
pickle_in_foldername = open('./utilities/folderdictionary.pickle','rb')
dictionary_foldername = pickle.load(pickle_in_foldername)
answer_folder = dictionary_foldername[userName.get()]
answer_folder=str(answer_folder)
CreateFolder.createFolder(answer_folder)
#Popen("./utilities/createAndHide.bat "+ userName.get() + " "+answer_folder)
flag=train.trainDataSet(empCode.get())
if(flag==True):
errorLabel.config(text="trained")
else:
errorLabel.config(text="not trained")
def defineRegister(flag,button):
if(flag):
userLabel = Label(text="enter your username")
userLabel.grid()
userEntry = Entry(textvariable=userName)
userEntry.grid()
empLabel = Label(text="enter your employeeCode")
empLabel.grid()
Entry(textvariable=empCode).grid()
Label(text="Duration for which Folder should be opened ").grid()
Entry(textvariable=duration).grid()
button = Button(text="DataSet Generation", command=lambda: lambda: saveDictionary()).grid()
def checkTime():
if getFolderName()!='not':
duration=getFolderName()[4:6]
return int(duration)
def lockFolder():
global locked
locked = True
#print 'here'
global timer_active
timer_active = 'no'
timerlabelcountdown.config(text='')
timerLabel.config(text='')
answer_folder = getFolderName()
#closeSubFolders(userName.get())
#os.system('nircmd win close title "%s"' %userName.get())
LockFolder.lockFolders(userName.get(),answer_folder)
#Popen("./utilities/lockFolder.bat "+userName.get()+" "+answer_folder)
global sub_folder
sub_folder = 'yes'
#user.configure(state=NORMAL)
unlockFolder_button.config(state=NORMAL)
userEntry.config(state=NORMAL)
empCodeEntry.config(state=NORMAL)
register_button.config(state=NORMAL)
lockFolder_button.config(state=DISABLED)
duration_box.config(state=NORMAL)
def getFolderName():
checkName = userName.get()
pickle_in_foldername = open(
'./utilities/folderdictionary.pickle',
'rb')
try:
dictionary_foldername = pickle.load(pickle_in_foldername)
answer_folder = dictionary_foldername[checkName]
except:
answer_folder = 'not'
return answer_folder
def lockFolder_crossButton():
if userName.get() != '':
answer_folder = getFolderName()
#####check if the folder has already been locked or not!!!!*********
if os.path.exists('./secretFolder/' + userName.get()):
LockFolder.lockFolders(userName.get(), answer_folder)
# Popen("./utilities/lockFolder.bat " + userName.get() + " " + answer_folder)
global timer_active
timer_active = 'no'
window.destroy()
def unlockFolder(checkName,answer_folder):
#Popen("./utilities/openFolder.bat " + checkName + " " + answer_folder)
UnlockFolder.unlock(checkName,answer_folder)
userEntry.config(state=DISABLED)
empCodeEntry.config(state=DISABLED)
unlockFolder_button.config(state=DISABLED)
lockFolder_button.config(state=NORMAL)
#duration.config(state=DISABLED)
def checkLock():
if locked==False:
lockFolder()
def countdown():
global timer_active
global remaining
if remaining <= 0 and timer_active == 'yes':
timerlabelcountdown.config(text="time's up!")
elif timer_active == 'yes':
timerlabelcountdown.config(text="%d" % remaining)
remaining = remaining - 1
timer = Timer(1, countdown)
timer.start()
def recogniseFace():
locked=False
lockFolder_button.config(state=NORMAL)
duration_box.config(state=DISABLED)
register_button.config(state=DISABLED)
errorLabel.config(text='')
timerlabelcountdown.config(text='')
if userName.get() == '':
errorLabel.config( text='User Name can not be left blank')
return
if save.findEmpCode(userName.get()) == 'not':
errorLabel.config(text='Please register yourself')
duration_box.config(state=NORMAL)
register_button.config(state=NORMAL)
return
final_time = checkTime()
if usertimer.get() != '':
try:
if int(usertimer.get()) < 1 or int(usertimer.get()) > 61:
errorLabel.config( text='Enter between 0 and 60 min')
return
final_time = int(usertimer.get())
except ValueError:
errorLabel.config( text='Enter a valid duration')
return
flag=dt.detector()
if flag==False:
errorLabel.config(text='Could not recognize you')
return
checkName=userName.get()
answer_folder = getFolderName()
print "checkName"+checkName+" flag="+flag
if(checkName==flag):
global timer_active
timer_active='yes'
timerLabel.config(text='Session is active')
global remaining
remaining=final_time*60
countdown()
unlockFolder(checkName,answer_folder)
timer = Timer(final_time * 60, checkLock)
timer.start()
Label(text="Welcome to the admin Screen").grid()
userLabel = Label(text="enter your username")
userLabel.grid()
userEntry = Entry(textvariable=userName)
userEntry.grid()
empLabel = Label(text="enter your employeeCode!")
empLabel.grid()
#empLabel.config(state=DISABLED)
empCodeEntry=Entry(textvariable=empCode)
empCodeEntry.grid()
#empCodeEntry.config(state=DISABLED)
durationLabel=Label(text="Duration for which Folder should be opened ")
durationLabel.grid()
duration_box=Entry(textvariable=duration)
duration_box.grid()
duration_box.config(state=NORMAL)
register_button=Button(text="Registeration",command=saveDictionary)
register_button.grid()
lockFolder_button=Button(text="Lock My Folder Please!",command=lockFolder)
lockFolder_button.grid()
lockFolder_button.config(state=DISABLED)
unlockFolder_button=Button(text="Unlock My Folder",command=recogniseFace)
unlockFolder_button.grid()
close_Application_Button=Button(text="Close Application",command=lambda:lockFolder_crossButton())
close_Application_Button.grid()
errorLabel.grid()
timerLabel.grid()
timerlabelcountdown.grid()
#window.protocol('WM_DELETE_WINDOW', lockFolder_crossButton)
window.mainloop()
There are a few problems with your code. Indention needs to be fixed, recogniseFace() has been defined twice in your code so you need to rename one of these functions and your import will not work due to no self() method existing in openApplication.py.
I believe your main problem is here.
if __name__ == '__main__':
from openApplication import self
self()
You are trying to import self from openApplication.py however you have not defined any method with the name self so python is unable to import self. That said you should never use self for anything other than its intended use inside of a class.
I believe what you should do is place your code inside of a function and then import that function.
In your openApplication.py file place all your code inside of a function and call it what you want. I think main() would work fine here.
Next in Facelock.launch.pyw replace your if __name__ == '__main__': section with this:
if __name__ == '__main__':
from openApplication import main
main()
This will correct the import error.

Proper way to kill a thread

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)

Python: print function hang when printing global list of objects

I'm currently writing a Python Telegram bot which is used to monitor Raspi IOs and send messages to a channel. So basically it has a function that will update a logging variable llog.
This function (logUpdate), as it's named, will remove entries that are more than 5 mins old. In it, I tried to check the content of the global variable. Upon printing, it just hangs.
This doesn't seem to block any other functionalities of the bot because I can still call out other bot commands.
I don't think it's the bot. It must be some kind of data access problems.
I attach some code snippet below:
#!usr/bin/python
##
### RF Security bot start script
##
##
### Imports
##
import telegram as tg
import telegram.ext as tgExt
import RPi.GPIO as gpio
import time
from datetime import datetime as dt
##
### Common variables
##
NULLSENSOR = 0
PRESSENSOR = 1
MAGSENSOR = 2
sensDict = {NULLSENSOR:"No sensor",
PRESSENSOR:"Pressure sensor",
MAGSENSOR:"Magnetic sensor"}
# Event class
class ev(object):
timestamp = 0
sType = NULLSENSOR
def __init__(self, ts=0, st=NULLSENSOR):
self.timestamp = ts
self.sType = st
def toString(self):
if(sType == PRESSENSOR):
return str("-> #"+timestamp.strftime('%c')+
": Pressure sensor triggered\n")
elif(sType == MAGSENSOR):
return str("-> #"+timestamp.strftime('%c')+
": Magnetic sensor triggered\n")
else:
return ""
# Report log
llog = [] # Data log
lmutex = True # Log mutex for writing
##
### Hardware configuration
##
# GPIO callbacks
def pressureCallback(channel):
global llog
global lmutex
global trigCntGlobal
global trigCntPress
ep = ev(ts=dt.now(), st=PRESSENSOR)
print("---> Pressure sensor triggered at "+
ep.timestamp.strftime("%c"))
rfSecuBot.sendMessage('#channel', "Pressure sensor "+
"triggered.")
while(not lmutex):
pass
lmutex = False
llog.insert(0, ep)
trigCntGlobal = trigCntGlobal + 1
trigCntPress = trigCntPress + 1
lmutex = True
def magneticCallback(channel):
global llog
global lmutex
global trigCntGlobal
global trigCntMag
global rfSecuBot
em = ev(ts=dt.now(), st=PRESSENSOR)
print("---> Magnetic sensor triggered at "+
em.timestamp.strftime("%c"))
rfSecuBot.sendMessage('#channel', "Magnetic sensor "+
"triggered.")
while(not lmutex):
pass
lmutex = False
llog.insert(0, em)
trigCntGlobal = trigCntGlobal + 1
trigCntMag = trigCntMag + 1
lmutex = True
# Periodic logging function
def logUpdate():
global llog
global lmutex
updTime = dt.now()
print("---> Updating log\n")
while(not lmutex):
pass
lmutex = False
for i in llog: ########### STUCK HERE
print(i.toString()) ###########
# Check log timestamps
for i in llog:
if((updTime - i.timestamp).total_seconds() > 300):
llog.remove(i)
for i in llog: ########### WAS STUCK HERE
print(i.toString()) ########### TOO
lmutex = True
print("---> Log updated\n")
# Formatting function
def logFormat():
global llog
global lmutex
logUpdate() # Asynchronous call to logUpdate to make sure
# that the log has been updated at the time
# of formatting
while(not lmutex):
pass
lmutex = False
flog = []
cnt = 0
for i in llog:
if(cnt < 10):
flog.append(i.toString())
cnt = cnt + 1
else:
break
lmutex = True
print("----> Formatted string:")
print(flog+"\n")
return flog
def listFormat():
global llog
global lmutex
logUpdate() # Asynchronous call to logUpdate to make sure
# that the log has been updated at the time
# of formatting
while(not lmutex):
pass
lmutex = False
flog = []
flog.append(" Sensors \n")
dLen = len(sensDict.keys())
if(dLen <= 1):
flog.append(sensDict.get(NULLSENSOR))
else:
sdItr = sensDict.iterkeys()
st = sdItr.next() # Had to add extra var
while(dLen > 1):
st = sdItr.next()
trigCnt = 0
for i in llog:
if(i.sType == st):
trigCnt = trigCnt + 1
if(trigCnt < 1):
pass
else:
flog.append("-> "+st+"\n")
flog.append(" No. of times tripped: "+
trigCnt+"\n")
lmutex = True
print("----> Formatted string:")
print(flog+"\n")
return flog
##
### Software configuration
##
def blist(bot, update):
print("--> List command received\n")
listString = "List of sensor trips in the last 5 minutes:\n"
listString = listString+listFormat()
print("> "+listString+"\n")
bot.sendMessage('#channel', listString)
def log(bot, update):
print("--> Log command received\n")
logString = "Log of last 10 occurrences:\n"
logString = logString+logFormat()
print("> "+logString+"\n")
bot.sendMessage('#channel', logString)
rfSecuBotUpd.start_polling(poll_interval=1.0,clean=True)
while True:
try:
time.sleep(1.1)
except KeyboardInterrupt:
print("\n--> Ctrl+C key hit\n")
gpio.cleanup()
rfSecuBotUpd.stop()
rfSecuBot = 0
quit()
break
## Callback registration and handlers are inserted afterwards
# Just in case...
print("--> Bot exiting\n")
gpio.cleanup()
rfSecuBotUpd.stop()
rfsecuBot = 0
print("\n\n\t *** EOF[] *** \t\n\n")
quit()
# EOF []
P.S. I think someone might suggest a 'class' version of this. Think it'll work?
In the toString function, I forgot to put self in front of the should-be members sType and timestamp:
def toString(self):
if(sType == PRESSENSOR):
return str("-> #"+timestamp.strftime('%c')+
": Pressure sensor triggered\n")
elif(sType == MAGSENSOR):
return str("-> #"+timestamp.strftime('%c')+
": Magnetic sensor triggered\n")
else:
return ""
Which is why the value returned was always an empty string.
Note to self: check your variables!!!
On that note, that kind of explained why it didn't seem to block the thread.

Categories

Resources