I'm experiencing an issue when calling a function inside a while loop.
The purpose of the while loop is to perform an action ,but it can only perform this action if a certain threshold appeared. This threshold is a result from another function.
When running this for the first time ,everything works ok. No threshold -no run.
The problem is ,that this threshold is affected by other parameters ,and when it changes ,it usually blocks the main program from running.
But ,at certain times, which I cannot pinpoint precisely when ,there's a "slip" and the threshold does not prevent the main program from running.
My question is ,could there be a memory leakage of some sort?
Code is below ,thanks.
def pre_run_check():
if check_outside() != 1:
return (0)
else:
return(1)
if __name__== '__main__':
while True:
time.sleep(0.5)
allow_action = None
while allow_action == None:
print ("cannot run")
try:
allow_action = pre_run_check()
except:
allow_action = 0
else:
if allow_action == 1:
print ("running")
#take action of some sort##
allow_action = None
def pre_run_check():
if check_outside() != 1:
return False
else:
return True
while True:
time.sleep(0.5)
allow_action = pre_run_check()
while not allow_action:
print ("cannot run")
try:
allow_action = pre_run_check()
if allow_action :
print ("running")
#take action of some sort##
allow_action = False
#Actualy need wait end of subprocess, Otherwise got some corrupted data/handle
break
except:
allow_action = False
time.sleep(.5)
This point is how to generate an sequential Process
Hope its helps.
Related
I need a program on raspberry pi, in which I can change the value of a variable delay while the program is running and is not interrupted by any input(). I came up with only one solution: read a value from a text file and change it using another program. But my solution doesn't work very well... When I overwrite a value in a text file, sometimes it happens that the program can't convert it to a float... sometimes it works well and sometimes it prints this error:
ValueError: could not convert string to float: ''
But the value in the text file seems to be fine...
So, this is main program:
def pause():
file = open('delay.txt', 'r')
pause = file.readline()
return pause
delay = float(pause())
while True:
GPIO.output(STEP, GPIO.HIGH)
delay = float(pause())
sleep(delay)
GPIO.output(STEP, GPIO.LOW)
delay = float(pause())
sleep(delay)
And this is the program, which is changing value in the text file:
while True:
rpm = float(input('RPM: '))
delay = (1/(rpm*60))/800
file = open('delay.txt', 'w')
file.write(str(delay))
file.close()
I really can't move with this... I'll be grateful for any advice and help in solving it.
You don't have to stick to my idea with a text file, maybe there is a better solution, but I couldn't think of anything better.
I'd suggest you use threading for this. I've made a small code example for you to get you started:
import threading
from time import sleep
import logging
logging.basicConfig(level=logging.DEBUG, filename="thread_output.txt", format='%(asctime)s %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s')
running = True
delay = 1
def worker(delay, running):
while running():
logging.debug(1)
sleep(delay())
logging.debug(0)
sleep(delay())
x = threading.Thread(target=worker, args=(lambda: delay, lambda: running))
x.start()
while running:
code = input("""
Make a choice:
1) Set delay
2) quit
""")
code = int(code)
if code == 1:
try:
val = input("Give up the desired delay between 0 and 10 seconds:")
val = int(val)
assert val >= 0 and val <= 10
delay = val
except ValueError:
print("Invalid input! Returning to home menu")
continue
elif code == 2:
running = False
else:
print("invalid option! Returning to home menu")
continue
print("quiting...")
x.join()
The part that helps you here is the fact that you pass the value of delay (and in the example also of running) as a lambda function. This means that every time the value is used, the value refetched. If you then were to change the value of the variable, it would get passed on :)
Hit me up if you have more questions!
In the case I am looping into a list, where for value msg_list = 0 it will execute action(0), usr). This action can fail for a determined user, I should choose aother user if it happens, perform all the actions related to the user
How can I do to repeat action[0] if it fails?
for msg in range(len(msg_list)):
# in this case msg = 0
usr = select_random_user()
multiple_actions_for(usr) # This are lots of code lines I don't want to repeat!!
try:
action(msg, usr)
more_actions(usr.related_stuff)
except Exception as e:
go_back_to(msg =0 instead of looping into msg=1) # this is what I want to do
How can I do to get that? Repeat the loop for msg = i instead of passing to msg = i + 1?
Put your code into the endless while-loop with exiting from it if try was successful:
for msg in range(len(msg_list)):
while True:
usr = select_random_user()
multiple_actions_for(usr)
try:
action(msg, usr)
more_actions(usr.related_stuff)
except Exception as e:
continue
else:
break
It really depends. Is it okay to go back to the beginning of the loop? If so, you can call "continue", which stops the current iteration, and restarts the loop. Otherwise, I don't think there's something similar to a goto in Python, no. It's a very structured language.
Try using while loop instead of for loop. The idea is as shown bellow:
bool still_looping = True
msg = 0
while still_looping:
usr = select_random_user()
multiple_actions_for(usr)
try:
action(msg, usr)
more_actions(usr.related_stuff)
if (msg < len (msg_list)):
msg += 1
except Exception as e:
# Do whatever you want here. msg was not incremented
if (msg == len(msg_list))
still_looping = False #verify if this was the last execution
Im trying to loop a function in itself in a special condition but as it re runs the function refreshes the variable "j" also. So i want to use that functions repeadetly to check connection and refresh the page so if i put variables to the out of the functions it will run once and makes it top value so the looping second time will fail. How to fix that?
def checkConnection():
onPage = pyautogui.locateCenterOnScreen('onpage.png', grayscale = True, confidence = 0.8)
noConnectionError = pyautogui.locateCenterOnScreen('noconnection.png', grayscale = True, confidence = 0.8)
sleep(2)
if onInstagram != None:
print("[INFO] : NETWORK STATUS : SUCCESS")
elif noConnectionError != None:
print("[WARNING] : NO CONNECTION !!!")
print("[INFO] TYRING TO RECONNECT...")
sleep(1)
j = 0
while j < 3:
print("[INFIO] REFRESHING PAGE... TRIAL : "+ str(j+1))
refresh()
sleep(3)
checkConnection()
print("[WARNING] : TRY AGAIN FAILED")
sleep(1)
print("[WARNING] : *****QUIT*****")
sleep(5)
quit()
I'm trying to design a control interface for my system which sends and receives some data through serial link. My searches related to GUI design took me to understand the "multi-threading" issue and code below shows the latest position I arrived.
This indicates similar parts (e.g try, run) with the ones I've seen on example GUIs. I planned to convert this to a GUI, once I understand how it exactly works.
So the problem is after I start, stop the code below I can't restart it again. Because, as I understand, multi-threading features only one cycle: start, stop and quit. I mean it doesn't accept start command after stop.
My question is how I can make this code to accept start after stopping?
Best wishes
import threading, random, time
class process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.leave = 0
print("\n it's running ...\n\n")
while self.leave != 1:
print "Done!"
time.sleep(1)
operate = process()
while True:
inputt = input(" START : 1 \n STOP\t : 0 \n QUIT\t : 2 \n")
try:
if int(inputt) == 1:
operate.start()
elif int(inputt) == 0:
operate.leave = 1
elif int(inputt) == 2:
break
except:
print(" Wrong input, try egain...\n")
Create process inside while True loop
if int(inputt) == 1:
operate = process()
operate.start()
It should work.
... but your code may need other changes to make it safer - you will have to check if process exists before you try to stop it. You could use operate = None to control it.
import threading
import random
import time
class Process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.leave = False
print("\n it's running ...\n\n")
while self.leave == False:
print("Done!")
time.sleep(1)
operate = None
while True:
inputt = input(" START : 1 \n STOP\t : 0 \n QUIT\t : 2 \n")
try:
if int(inputt) == 1:
if operate is None:
operate = Process()
operate.start()
elif int(inputt) == 0:
if operate is not None:
operate.leave = True
operate.join() # wait on process end
operate = None
elif int(inputt) == 2:
if operate is not None:
operate.leave = True
operate.join() # wait on process end
break
except:
print(" Wrong input, try egain...\n")
Other method is not to leave run() when you set leave = True but keep running thead. You would need two loops.
def run(self):
self.leave = False
self.stoped = False
print("\n it's running ...\n\n")
while self.leave == False:
while self.stoped == False:
print("Done!")
time.sleep(1)
Cont = 1
while Cont == 1:
try:
while Cont == 1:
counter = counter + 0.1
counter = round(counter, 1)
print(counter)
time.sleep(0.1)
if counter == crashNumber:
Cont = 0
except KeyboardInterrupt:
Multiplier = counter
Here the counter will continue to count up unitl it reaches the crashNumber, when Ctrl + C is pressed, it will take the number that the counter is at and use it for the Multiplier to be used later.
However I only want to give the user the chance to press this once, then it is disabled. Is there any way that this can be done?
The KeyboardInterrupt exception will be thrown whether you want it or not: the solution, then, is to deal with the exception in different ways in your except block. My chosen implementation will use a simple boolean value that starts as True and is set to False on the first interruption:
import time
allow_interrupt = True
while True:
try:
time.sleep(1)
print ('...')
except KeyboardInterrupt:
if allow_interrupt:
print ('interrupted!')
allow_interrupt = False
Let me know if this addresses your use case.