Python to run a specific flask program until hitting another button - python

I have a sweep function that returns a string of data. What I want to do is have two buttons, a start button and a stop button. When the start button is hit, the sweep function is called, and once that function is finished it is called again and again and again. Running nonstop until the stop button is hit. I'm using flask.
I don't think this is a duplicate because most of the other question regarding this want it to stop at a specific time, ie. run for 45 seconds. I need mine to run continuously until the stop button is pressed.
My thought process was to do something like
#app.route('continue_sweep', methods=["GET","POST")
def continue_sweep():
while (sweep_continue flag = true):
sweep()
and then in my stop button function just have a sort of break all? I don't know if that's a thing or not, but that was my thought process.
#app.route('stop_sweep', methods=["GET","POST"])
def stop_sweep():
break all -->> end the above sweep function here
--------------------Updated code
I can do something like this
#app.route('/start_continue_sweep', methods=["GET","POST"])
def start_continue_sweep():
if init_tester_flag == False:
initialize_tester()
stop_btn_flag = False
while (stop_btn_flag == False):
sweep_continue_fun()
return render_template('sweep_results.html', sweep_str = remove_err_str)
def sweep_continue_fun():
sweep_btn()
return render_template('sweep_results.html', sweep_str = remove_err_str)
and it gives me what I want, but does not update the sweep_results.html. Is this why I would need something like what was mentioned in your answers below? Or is there an easier fix to make it update?

That's not how web requests work. One request gets one response, then it's done. If you want something to move continuously, you will have to do that with Javascript in the browser, not in the server.

Related

Python Playwright make code reload page after timeout until it finds the object

I want the code to reload the page if it doesn't find the desired object (e.g. a button) after a given timeout time. The code should reload the page until it finds the object and then continue. Is there any way to do it in python playwright?
I've read the documentation, but I didn't find anything, any help is appreciated.
You can define your own function like this one:
def my_own_wait_for_selector(page, selector, time_out):
try:
page.wait_for_selector(selector, timeout=time_out)
return True
except:
return False
That function will wait for a selector and if given some time (miliseconds) the element is not there it will return False instead of trowing an error.
Then in your code you could try something like:
while not my_own_wait_for_selector(page, "my_button_selector", 5000):
page.reload()
page.locator("my_button_selector").click()
As you can see we are checking if our button is present, and we will wait only 5 seconds, if after 5 seconds the button is not there, we will reload, and again and again until our button is there, once our button is there code will continue and then we will click the button.
Be careful, because if your button is never there, your script will reload and your script will never finish, so you should add some other condition to your while

A function is running despite me changing a variable that should stop it

I was hoping someone could help me with this issue. I'm hoping it's fairly simple to fix, but I have been trying for a while to figure this out. I have trimmed my larger code to this, as I believe the issue here is the crux of the problem.
I have a raspberry pi and an external button. This is on python3 on Linux. I am using GPIOZero for the button. The code below I believe is simple to understand, but basically, I want a function to loop at all times. When I press a button I want another function to run, but only if a variable is a certain number. I describe what I ultimately want to happen in a comment below, but my code is unfinished and simplified just for this problem.
I only want button.when_pressed to work when timer = 0. The problem is, once the code naturally gets into the button.when_pressed function, it never "lets go" of the function again. When I successfully redefine the variable to timer = 1, it still prints button is pressed when I press the button. I don't know why. To me, it seems like it should only work once timer = 0.
Any suggestions? I think I have a misunderstanding of global variables I will plan on researching. I'm not sure if that's the issue. I have also tried using break and continue to try to get it "back on its loop" but that hasn't worked either. Also I want to use button.when_pressed instead of btn.is_pressed, because I want the program to only do something when I'm holding the button down once, and not loop when I'm holding it down. In this case, I want button is pressed to print a single time. If I did btn.is_pressed it would print button is pressed every two seconds, which I dont want.
Thanks for any help. I'm happy to learn.
#!/usr/bin/python3
from gpiozero import Button
from time import sleep
import time
button = Button(4)
timer = 0
def press():
print("Button is pressed")
global timer
timer = 1
def loop():
global timer
timer = 1
while True:
if timer == 0:
button.when_pressed = press
else:
loop()
sleep(2)
If you want to disable the callback you had set to button.when_pressed, you need to do another assignment with button.when_pressed = None. This is listed in the documentation:
when_released:
[...] Set this property to None (the default) to disable the event.
It's not exactly clear what behavior you want from your current code. If you want the button to be active for 2 seconds, then be deactivated indefinitely, you can use:
button.when_pressed = press
sleep(2)
button.when_pressed = None
There's no need for a loop, since you don't want to repeat anything.
If you only want the button to be active for a single button press, that needs to happen within 2 seconds, you could instead call button.wait_for_press(2). I hesitate to write a full block of code for that though, as the docs don't specify how a timeout is signaled (it might be by return value, or via an exception). I don't have a Raspberry Pi so I can't test myself, but you could try it out and see what happens.
Treat your whole piece of code as one "black box", ask yourself, what is the input/output? button press or timer mode? (because I don't quite understand what does timer variable mean in your code)
Your code implies timer mode is the top level input to control the flow,
while True:
if timer == 0:
button.when_pressed = press
else:
loop()
sleep(2)
Is it expected?
If you allow user to press the button at any time, suggest you make button press to be your top level input, change the logic to keep when_pressed callback always on, set flag once triggered, and then check if the button has been pressed and still is_pressed in your while loop.
pressed = False
def play_video_1():
pass
def play_video_2():
pass
def press():
print("Button is pressed")
global pressed
pressed = True
button.when_pressed = press
while True:
if pressed and not_playing_video2:
if is_pressed:
play_video_1()
else:
pressed = False
play_video_2()
else:
play_video_2()

How to stop repeat on button press/hold - Python

I was hoping someone might have some insight on how to stop a script from continuing to repeat if a button is held (or in my case pressed longer than a second)?
Basically i've a button setup on the breadboard, and I have it coded to play an audio file when the button is pressed. This works, however if the button isn't very quickly tapped, then the audio will repeat itself until button is fully released. Also if the button is pressed and held, the audio file will just repeat indefinitely.
I've recorded a quick recording to demonstrate the issue if its helpful, here: https://streamable.com/esvoy6
I should also note that I am very new to python (coding in general actually), so its most likely something simple that I just haven't been able to find yet. I am using gpiozero for my library.
Any help or insight is greatly appreciated!
Here is what my code looks like right now:
from gpiozero import LED, Button
import vlc
import time
import sys
def sleep_minute(minutes):
sleep(minutes * 60)
# GPIO Pins of Green LED
greenLight = LED(17)
greenButton = Button(27)
# Green Button Pressed Definition
def green_btn_pressed():
print("Green Button Pressed")
greenButton.when_pressed = greenLight.on
greenButton.when_released = greenLight.on
# Executed Script
while True:
if greenButton.is_pressed:
green_btn_pressed()
time.sleep(.1)
print("Game Audio Start")
p = vlc.MediaPlayer("/home/pi/Desktop/10 Second Countdown.mp3")
p.play()
So from a brief look at it, it seems that 'time.sleep(.1)' is not doing what you are expecting. Ie. it is obviously interrupted by button presses. This is not abnormal behaviour as button presses on Ardiuno and raspPi (guessing here) would be processed as interrupts.
The script itself does not contain any prevention from double pressing or press and hold etc.
Have you put in any debug lines to see what is executing when you press the button?
I would start there and make adjustments based on what you are seeing.
I am not familiar with this gpiozero, so I can't give any insight about what it may be doing, but looking at the code and given the issue you are having, I would start with some debug lines in both functions to confirm what is happening.
Thinking about it for a minute though, could you not just change the check to 'if greenButton.is_released:'? As then you know the button has already been pressed, and the amount of time it is held in for becomes irrelevant. May also want to put in a check for if the file is already playing to stop it and start it again, or ignore and continue playing (if that is the desired behaviour).
Further suggestions:
For this section of code:
# Executed Script
while True:
if greenButton.is_pressed:
green_btn_pressed()
time.sleep(.1)
print("Game Audio Start")
p = vlc.MediaPlayer("/home/pi/Desktop/10 Second Countdown.mp3")
p.play()
You want to change this to something along these lines:
alreadyPlaying = 0
# Executed Script
while True:
if greenButton.is_pressed:
green_btn_pressed()
#Check if already playing file.
if alreadyPlaying == 1:
# Do check to see if file is still playing (google this, not sure off the top of head how to do this easiest).
# If file still playing do nothing,
#else set 'alreadyPlaying' back to '0'
break
#Check if already playing file.
if alreadyPlaying == 0:
time.sleep(.1)
print("Game Audio Start")
p = vlc.MediaPlayer("/home/pi/Desktop/10 Second Countdown.mp3")
p.play()
alreadyPlaying = 1
Hopefully you get the idea of what I am saying. Best of luck!
i think you have to write something like this in your loop:
import time, vlc
def Sound(sound):
vlc_instance = vlc.Instance()
player = vlc_instance.media_player_new()
media = vlc_instance.media_new(sound)
player.set_media(media)
player.play()
time.sleep(1.5)
duration = player.get_length() / 1000
time.sleep(duration)

Controlling flow of application using GUI interface

(Thanks in advance if you decide to answer. Sorry If I am not able to describe the content of the Application clearly.)
I am currently making Desktop Application using Tkinter Python for my gui interface. I am having a problem related to the flow of the Application.
My Application
Main Page of my application has form designed with some textboxes and checkboxes. Check button work as True or False Condition, where each check button refers to whether or not a specific function has to be executed or not.
To store the values of the check button, the dictionary is maintained with keys as LabelName and values as True/False value.
Checkbox code
f1=tk.BoolVar() #People tend to use IntVar() but i prefer BoolVar()
ttk.Label(text="func1")
ttk.Checkbutton(parent, variable=f1)
f2=tk.BoolVar()
ttk.Label(text="func2")
ttk.Checkbutton(parent, variable=f2)
-------other such CheckButtons------------------
There's a submit button in the form on pressing which all the data entered into textbox along with these check buttons. Based on true-false values, functions are called which is handled by if-else conditions.
#submit button
ttk.Button(parent,text="Submit",command=onsubmit)
###########
def onsubmit():
----------statements to read data--------------
dict['func1']=f1
dict['func2']=f2
#other statements
-----------------------------------------------
if dict['func1']:
func1()
if dict['func2']:
func2()
---other if-else conditions---
Each function is individual module which consists of either form, or frame with data or matplotlib graphs for visualization of data and to do other operations on data and graphs which are placed on root window frame.
My problem
I want the user to control the flow by giving them the next button after every function is executed and then move onto the execution of the next function based on his input of the check button. The program should wait until the User presses the next button and after they press the next button, it should execute the next function and then wait again for the next button.
One of the solution:
Using fig.waitforbuttonpress() was the solution. But I didn't find it reliable. Because even mouse click could skip the function execution. But I need to specifically assign a button through which the user can select when to proceed to the next function.
I am not sure if I understood what your code does, but you could do it something like that I guess:
next_button = ttk.Button(parent,text="Next",command=func1)
...
def func1():
#do your stuff here
next_button.configure(command=func2)
Then you would have to add the last line of code to all the functions to always reassign the button.
Another way could be:
process = 0
next_button = ttk.Button(parent,text="Next",command=next)
def next():
global process
process += 1
if process == 1:
func1()
elif process == 2:
func2()
...
elif *last_function_reached*:
process = 0

How to start and stop a while-loop with an ipywidget interactive Checkbox?

i try to start and stop a while-loop with a simple checkbox. But i don't know how i am able to update the checkbox-state in the while loop.
Below you can see what i have, but when i uncheck the box, the while loop won't recognize it.
I searched through the interactive functions but have not found any function to get the updated state of the checkbox.
Hope you guys can help me out :)
import ipywidgets
import time
def f(x):
while x==True:
print("!")
time.sleep(1)
c=ipywidgets.interactive(f,x=False)
c
If you create the checkbox explicitly with:
checkbox = widgets.Checkbox(description='click me')
... you can get the current value with checkbox.value.
Annoyingly, that's not enough to just allow your checkbox to halt the execution of a while loop. Once your while loop has started, it occupies the Python interpreter. There is therefore no space for the checkbox changes to be interpreted until the while loop finishes.
Since this is fundamentally a concurrency problem (you want to react to changes in the checkbox while also running a computation), you need to use Python's concurrency primitives. You can, for instance, achieve this with coroutines:
import ipywidgets as widgets
import asyncio
class HaltableExecutor:
def __init__(self, checkbox):
self._checkbox = checkbox
async def my_code(self):
# This is your user code
while True:
if self._checkbox.value:
print('running') # put your code here
await asyncio.sleep(0.1) # use this to temporarily give up control of the event loop to allow scheduling checkbox changes
def start(self):
print('starting')
asyncio.ensure_future(self.my_code())
Then, create and display your checkbox:
c = widgets.Checkbox(description='click me')
c
... and start your executor:
exe = HaltableExecutor(c)
exe.start()
The while loop will now run. At every iteration, we pause to give up control of the event loop with asyncio.sleep. The amount we sleep by is irrelevant, the point is to give control back. This gives the main thread an opportunity to deal with outstanding messages like checkbox changes. At the next iteration of the while loop, self._checkbox.value is checked again and so on.

Categories