change value when python is in infinite loop - python

Can this be done in python?
Start by print an infinite loop and changing values in between loops.
x = 5
while ( true ):
print x
x = 3 # regain control of the interpreter and set to new value
expected output:
5
5
5
......
3
3
3

No, the code as you have written it will not work. The statement after the non-terminating loop will never get executed.
Try the following:
x = 5
while True:
if (some-condition):
x = 3
print x
Alternatively, use threading, and change the value of x in a second thread:
def changeX():
global x
x = 3
x = 5
import threading
threading.Timer(3, changeX).start() # executes changeX after 3 seconds in a second thread
while True:
print x

It's unclear what you need to do this for, but you can catch the "ctrl-c" event and enter a new value:
x = 5
while True:
try:
print x
except KeyboardInterrupt:
x = raw_input("Enter new value: ").strip()

I think that the best answer to this question is to use threading, but there is a way to inject code into a running interpreter thread:
https://fedorahosted.org/pyrasite/

Not exactly. Why do you want to do this? What's the underlying issue?
The "right" way to do it is probably to change the code within the while loop to occasionally actually check for your condition and then end the loop if it's time to end it (e.g., have a thread continue watching for console input)
With that said, technically you could attach to your running program with a debugger (such as winpdb or the built in pdb and mess with it.
But what you probably want to do, if I'm guessing right about your underlying motives, is continue to accept input despite doing some other processing simultaneously.
In that case, you want to learn how to use threads in Python. Check the threading module.

Related

How to while loop that only run when certain condition is met

I want a while loop that only run when certain condition is met. For example, I need to loop the condition A if listposts != 0 and listposts != listView: to check whether there is a new record or not. If it found a new record it will do function B and stop until the condition is met again.
I'm new to programming and I tried with this code but its still looping endlessly.
while True:
if listposts != 0 and listposts != listView:
Condition = True
while Condition == True :
function B()
Condition = False
What I want to achieve is the loop will stop after 1 loop and wait until the condition is met to loop again.
From what you expect as behavior you need 3 things:
a condition-test (as function) returning either True or False
a loop that calls the condition-test regularly
a conditional call of function B() when condition is met (or condition-test function returns True)
# list_posts can change and is used as parameter
# listView is a global variable (could also be defined as parameter)
# returns either True or Fals
def condition_applies(list_posts):
return list_posts != 0 and list_posts != listView
# Note: method names are by convention lower-case
def B():
print("B was called")
# don't wait ... just loop and test until when ?
# until running will become False
running = True
while running:
if condition_applies(listposts):
print("condition met, calling function B ..")
B()
# define an exit-condition to stop at some time
running = True
Warning: This will be an endless-loop!
So you need at some point in time to set running = False.
Otherwise the loop will continue infinite and check if condition applies.
To me it seems that you have a producer/consumer like situation.
IMHO your loop is ok. The principle applied here is called polling. Polling keeps looking for new items by constantly asking.
Another way of implementing this in a more CPU optimized way (using less CPU) requires synchronization. A synchronization object such as a mutex or semaphore will be signaled when a new element is available for processing. The processing thread can then be stopped (e.g. WaitForSingleObject() on Windows), freeing the CPU for other things to do. When being signaled, Windows finds out that the thread should wake up and let's it run again.
Queue.get() and Queue.put() are such methods that have synchronization built-in.
Unfortunately, I see many developers using Sleep() instead, which is not the right tool for the job.
Here's a producer/consumer example:
from threading import Thread
from time import sleep
import random
import queue
q = queue.Queue(10) # Shared resource to work on. Synchronizes itself
producer_stopped = False
consumer_stopped = False
def producer():
while not producer_stopped:
try:
item = random.randint(1, 10)
q.put(item, timeout=1.0)
print(f'Producing {str(item)}. Size: {str(q.qsize())}')
except queue.Full:
print("Consumer is too slow. Consider using more consumers.")
def consumer():
while not consumer_stopped:
try:
item = q.get(timeout=1.0)
print(f'Consuming {str(item)}. Size: {str(q.qsize())}')
except queue.Empty:
if not consumer_stopped:
print("Producer is too slow. Consider using more producers.")
if __name__ == '__main__':
producer_stopped = False
p = Thread(target=producer)
p.start()
consumer_stopped = False
c = Thread(target=consumer)
c.start()
sleep(2) # run demo for 2 seconds. This is not for synchronization!
producer_stopped = True
p.join()
consumer_stopped = True
c.join()

Is there a method for making a function run continuously until a user tells it to stop?

I'm currently trying to write a program for a raspberry pi in Python 3 to control a set of linear actuators situated on a table that will both change the length of the legs and allow for the table top to be angled. One of the features of the table is an automatic leveling feature to ensure that the tabletop is is always level and will self correct if it detects it is not by pulling data from an onboard accelerator. The autolevel feature works perfectly fine however I am having difficulty programming on and off conditions. Ideally typing a(1) in the console will call the autolevel function and cause it to run continuously until typing a(0) stops it. I managed to get the function to run by typing a(1) but once that command is accepted the program stops listening for further commands and loops endlessly. The code in its current state is posted bellow.
def a(n):
while n== 1:
acceleration = sense.get_accelerometer_raw()
x = acceleration['x']
y = acceleration['y']
z = acceleration['z']
x=round(x, 3)
y=round(y, 3)
z=round(z, 3)
if x >0.00:
GPIO.output(12,0)
GPIO.output(13,1)#leg 1 retract
GPIO.output(15,0)
GPIO.output(29,1)#leg 2 retract
GPIO.output(31,1)
GPIO.output(32,0)#leg 3 extend
GPIO.output(33,1)
GPIO.output(36,0)#leg 4 extend
sense.show_message('Correcting forward tilt')
elif x <0.00:
GPIO.output(12,1)
GPIO.output(13,0)#leg 1 extend
GPIO.output(15,1)
GPIO.output(29,0)#leg 2 extend
GPIO.output(31,0)
GPIO.output(32,1)#leg 3 retract
GPIO.output(33,0)
GPIO.output(36,1)#leg 4 retract
sense.show_message('Correcting rearward tilt')
else:
if y >0.00:
GPIO.output(12,0)
GPIO.output(13,1)#leg 1 retract
GPIO.output(15,1)
GPIO.output(29,0)#leg 2 extend
GPIO.output(31,0)
GPIO.output(32,1)#leg 3 retract
GPIO.output(33,1)
GPIO.output(36,0)#leg 4 extend
sense.show_message('Correcting right side tilt')
elif y <0.00:
GPIO.output(12,1)
GPIO.output(13,0)#leg 1 extend
GPIO.output(15,0)
GPIO.output(29,1)#leg 2 retract
GPIO.output(31,1)
GPIO.output(32,0)#leg 3 extend
GPIO.output(33,0)
GPIO.output(36,1)#leg 4 retract
sense.show_message('Correcting left side tilt')
else:
sense.show_message("No tilt to correct")
print ("Stand currently level, standing by for reactive adjustment.")
You can use multi threading,
here is how you can incorporate it into:
You will be asked to enter value which in your case would be "exit" keyword.
Let me know if worked.
import threading
flag=False
def a1():
global flag
a= flag
#if(a==True):
while (!a):
acceleration = sense.get_accelerometer_raw()
x = acceleration['x']
y = acceleration['y']
z = acceleration['z']
#paste the rest of your code here
def loopBreak():
"""
function to exit the loop
"""
global flag
inp=input("Enter value")
if inp=="exit":
flag =True
if __name__ == "__main__":
# creating thread
t1 = threading.Thread(target=a1)
t2 = threading.Thread(target=loopBreak)
# starting thread 1
t1.start()
# starting thread 2
t2.start()
# wait until thread 1 is completely executed
t1.join()
# wait until thread 2 is completely executed
t2.join()
print(flag)
# both threads completely executed
print("Done!")

How to Print Something Every Other Time Something Happens

I'm trying to learn python and while learning I've come across a bit of a problem.
import time
import pyautogui
def SendScript():
time.sleep(2)
with open('script.txt') as f:
lines = f.readlines()
for line in lines:
time.sleep(2)
pyautogui.typewrite(line.strip())
pyautogui.press('enter')
SendScript()
I'm trying to print something to the screen every second time the 'enter' key has been pressed, but I'm an extreme beginner so I really don't know how to do that. Could someone help me accomplish this task?
You could create a new boolean variable to track if the enter key has been pressed before. That way, every time the for loop iterates, the value of pressed switches and only when the value of pressed is True will it print something.
import time
import pyautogui
def SendScript():
pressed = False
time.sleep(2)
with open('script.txt') as f:
lines = f.readlines()
for line in lines:
time.sleep(2)
if pressed:
print("Something")
pressed = not pressed
pyautogui.typewrite(line.strip())
pyautogui.press('enter')
SendScript()
From a more step-back approach, you could do:
events=['event1', 'event2', 'event3', 'event4', 'event5', 'event6', 'event7', 'event8']
counter = 0
for event in events:
counter += 1
if counter % 2 == 0: # ie do stuff when divisible by 2, ie when its even
print('print what you want to be printed every second time')
else:
pass
Of course you are not looping through events like I do in this example. The point is counting the events and only doing stuff when this count is even.
As indicated in another answer already, a simple toggle can be implemented with a bool and then code which toggles it every time something happens:
thing = False
:
if happens(something):
thing = not thing
This is fine for toggling between two states. A more general approach which allows for more states is to use a numeric variable and a modulo operator:
times = 0
maxtimes = 12
:
if happens(something):
times += 1
if times % maxtimes == 1:
print("ding dong")
The modulo could be compared to 0 instead if you want to print on the 12th, 24th etc iterations instead of the first, the 13th, etc, or of course any other offset within the period if that's what you want.
Another useful trick is to flip-flop between zero and some other value.
value = 0
othervalue = 1234
:
if happens(something):
value = othervalue - value
Of course, you can flip-flop between any two values actually; subtract the current value from their sum to get the other one.
Needless to say, just toggling or flip-flopping isn't very useful on its own; you'd probably add some (directly or indirectly) user-visible actions inside the if happens(something): block too.
You could use a generator for this:
def everySecondTime():
while True:
yield "hi"
yield "not hi"
mygen = everySecondTime()
print(next(mygen))
print(next(mygen))
print(next(mygen))
print(next(mygen))
This prints
hi
not hi
hi
not hi
I'm sure it's clear to you how you could adapt this to do some other actions instead.
Whether this approach is better than just using a boolean is highly debatable, but I thought I'd leave it here so you could learn about generators (the yield keyword) if you want to.

Check if a condition is respect instantly

I have a complex project and I will try to simplify one of the main problem of the project. So there is the simplification:
We can Imagine a while loop like this:
while(condition):
statement1
statement2
statement3
...
statementn
In this loop there n statements, and each statement can be whatever(function, loop, if statement,...) and there is a condition in the loop, this condition i want to check it BEFORE the while loop do it. Because if the condition is respect since the first statement I have to wait until the end of the while to check if the condition is respect... So there is my question is possible to check the condition BEFORE the loop without have a check-function between EACH statements of the whileloop ?
Because in fact, it's work... BUT the code isn't clear, I really think this way we pollute my code and i want to work more efficiently and with a beautiful code, so how can I solve my problem without this constraint ?
PS: I think about event listener like javascript but i found poor information about them on python, but if there is a tool which act like event listener it would be great !
It sounds like you want to clean up all your if-then-break statements into a single function that handles the "checking" of the value of a. For that purpose you could use exceptions:
import random
class ItIsFiveException(Exception): pass
def check(a):
if a == 5:
raise ItIsFiveException
try:
a = 0
while(a != 5):
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
a = random.randint(1,5); check(a)
except ItIsFiveException:
print("I saw a five!")
You just have to define your own python Exception as a class, and the raise it in your manually-defined check(a) function. Then you can wrap your entire while loop in a try-except block and catch your exception.
I am not sure if I understand you right, but this is what I'd do:
flag = False
while not flag:
for i in range(4):
a = random.randint(1, 5)
if a == 4:
flag = True
break
I don't know exactly what it happens with "a" but if if you can chain the conditions and will stop when the first one fails
while(checkRandom()):
...
def checkRandom(a):
return random.randint(1,5) == 5 and random.randint(1,5)....
If you can loop the generation of random values you can use
while(a!=5):
for item in range(1, 5):
a=random.randint(1,5)
if a==5:
break

Is there a variation of the while loop that will only run the clause once until a change occurs?

Sorry about the title, this is a bit of a tough question to phrase. I'm using Python. Basically, I want the program to check a variable indefinitely. If the variable goes above 100 for example, I want code block A to run only once, and then I want the program to do nothing until the variable goes back below 100, then run code block B, and wait again until the variable goes back above 100, and then run block A again, and repeat.
The current setup I've written is as follows:
while on = True:
if value_ind >= 100:
open_time = time()
else:
close_time = time()
calculate_time_open(open_time, close_time)
The obvious problem here is that whichever if/else code block is true will run itself indefinitely, and create multiple entries in my lists for only one event. So, how would I make the code blocks run only once and then wait for a change instead of repeating constantly while waiting for a change? Thanks in advance.
You can use a state machine: your program is in one of two state: "waiting for a high/low value" and behaves appropriately:
THRESHOLD = 100
waiting_for_high_value = True # False means: waiting for low value
while True: # Infinite loop (or "while on", if "on" is a changing variable)
if waiting_for_high_value:
if value_ind >= THRESHOLD:
open_time = time()
waiting_for_high_value = False
else: # Waiting for a low value:
if value < THRESHOLD:
close_time = time()
calculate_time_open(open_time, close_time)
waiting_for_high_value = True
Now, you do need to update you test value value_ind somewhere during the loop. This is best done through a local variable (and not by changing a global variable as an invisible side effect).
PS: The answer above can be generalized to any number of states, and is convenient for adding some code that must be done continuously while waiting. In your particular case, though, you toggle between two states, and maybe there is not much to do while waiting for a change, so Stefan Pochmann's answer might be appropriate too (unless it forces you to duplicate code in the two "wait" loops).
How about this?
while True:
# wait until the variable goes over 100, then do block A once
while value_ind <= 100:
pass
<block A here>
# wait until the variable goes below 100, then do block B once
while value_ind => 100:
pass
<block B here>
This solves your repetition issue. You might better actually wait rather than constantly checking the variable, though, although it depends on what you're actually doing.
Added: Here it is with the actual blocks A and B from your code and using not, which maybe makes it nicer. One of them with parentheses which maybe highlights the condition better. (And with pass not on an extra line... I think that's ok here):
while True:
while not value_ind > 100: pass
open_time = time()
while not (value_ind < 100): pass
close_time = time()
calculate_time_open(open_time, close_time)

Categories

Resources