I have a python script that goes like this -
import..
def main ():
some_condition check
main() #calling main again
some condition check
main() #calling main again
main()
The idea here is to let the script run indefinitely and check for something.
This way of calling main() somehow seems incorrect.
I am quite new to Python scripting. Can someone guide me if this very inefficient and if yes then how do I achieve this?
What you are doing is called recursion. This is certainly not good for long running applications, since it would cause a stack overflow.
Do your checking like this:
quit = False
while not quit:
do_your_check()
#maybe sleep
quit = should_i_stop()
Just put the things you want to do in a while true loop.
import ...
def main():
while True:
some_condition check
Recursion is utilized when it is too complex/hard to write as iterative code. e.g. Tree traversals.
Related
I would like to exit a function by pressing a button using the return statement in the if statement. To write these lines again and again and again is not really what I like. That's why I am basically looking for a function that tells the parent function to return.
Obviously I can't use the return statement in a function and just execute the function where I want to check the variable, although that would be the nicest way I could imagine.
I want to explain it in a loop, but please keep in mind that's not where I want to use it. The usage is for automated processes which should have many exit points.
import keyboard, time
RedFlag = False
def set_RedFlag():
global RedFlag
RedFlag = True
keyboard.add_hotkey("end", set_RedFlag)
PauseFlag = False
def set_PauseFlag():
global PauseFlag
print(PauseFlag)
if PauseFlag == False:
PauseFlag = True
else:
PauseFlag = False
keyboard.add_hotkey("space", set_PauseFlag)
def task():
for i in range(30):
print("test",i)
time.sleep(1)
# Flags
if RedFlag == True: # exitpoint
return
while PauseFlag == True: # pause the script
time.sleep(1/6)
task()
Really relevant is the if statement after #Flags. Especially with the while statement I would have to repeat multiple lines. I would love to have this in one single word as if it was a function.
Edit:
More about the "what for?":
I would like to run a macro and later maybe other tasks. For example writing the odd numbers from 1 to 511. And I want to be able to stop or pause it at any given time.
I forgot to mention, that I tried using the multiprocessing module, since I could terminate the task there. Sadly it is not an option for me not only because the starting time of a process is a bit too long for me, also I am learning a bit about kivy and I know it get's complicated when I want to start another process while using kivy.
I'm making a Discord bot with a lot of commands that take a while to finish (like loops) so I'd like to also have a command that stops any actively running code. I've tried sys.exit but I don't want to have to restart the program each time before it will take another input. Anyone know what I can do?
It will depend on the way your code is formatted, but you will probably want to use functions that utilize boolean or return statements:
def foo():
if end_this:
return
# stuff
If you have some tracking boolean end_this that is set to True, the function foo() will not execute everything below. Alternatively, you could use a while-loop with a break in your code:
def foo():
while True: # runs forever unless ended
# stuff
break
Now, foo() will continue indefinitely until the break statement is reached. An if-statement can enclose the break, setting some logic on when the break occurs. Again, this may require a main() function to handle the calls and ends of your previous functions, but it would allow following code/functions to execute.
How do I get main to run again without executing the whole script again?
import sys #importing module that is used to exit the script
def main ():
#doing stuff
main ()
#Re-run the script - looking for a cleaner way to do this!
def restart ():
restart = input("Press any key + Enter to start again, or x + Enter to exit.")
if(restart != "x"):
exec(open("./calc.py").read())
# not sure how to run main() again without calling out the script name again?
else:
print ("Exiting!")
sys.exit ((main))
restart ()
#End of Program
You can re-run the main module-method as many times as you want by directly calling main() sequentially:
def main( ):
# Code goes here...
return;
main();
main();
main();
However, if you want the user-interaction like your restart method has, you might want to consider defining main with an optional parameter (one that has a default value) that controls whether you ask to re-run the method or not.
def main( argv, AskRestart= True ):
# Main code goes here....
if ( AskRestart ):
# User interaction code goes here ...
return;
Also, you can look into the atexit package in Python 3.5.1 to see how you can assign a method to be run only when exiting the interpreter:
https://docs.python.org/3.5/library/atexit.html
That would allow you to do whatever you want and then when everything is done, give someone the option of restarting the entire module. This would remove the reliance on the exec call, and be a more coherent and simpler approach to getting the exact same expected functionality.
In addition to Tommy's great advice, (I'm not sure of your goal in continually restarting main() as main is an empty function that doesn't do anything yet, but..) one way to have main continually repeat until the user enters x may be to use a while True loop:
import sys #importing module that is used to exit the script
def main ():
#doing stuff
restart() # <-- use main to restart()
#Re-run the script - looking for a cleaner way to do this!
def restart ():
restart = raw_input("Press any key + Enter to start again, or x + Enter to exit.")
while True: # <-- key to continually restart main() function
if(restart != "x"):
exec(open("./calc.py").read())
# not sure how to run main() again without calling out the script name again?
main() # <-- restart main
else:
print ("Exiting!")
sys.exit ((main))
restart ()
#End of Program
Hope this also helps!
I have a problem in managing a infinite while loop in Python, in which I would insert a timer as a sort of "watchdog". I try to explain better: the script has to listen on a serial channel and wait for messages coming from sensors connected on the other side of the channel.
I do this with a while True loop because the script must catch all the signals that are passing. However, even if it's probably unnecessary, i would like to insert a timer which is always reset every loop. So, if (for example) the loop get stuck for some reason, the timer will end and will exit the program. I thought i could do this in this way:
def periodicUpdate():
exitTimer = threading.Timer(60.0, sys.exit())
while True:
exitTimer.start()
readData()
exitTimer.cancel()
Now, the problem is that when i start the script it immediatly exit. It seems that it reads sys.exit() before all the rest, and it doesn't respect the construct of the timer, but simply when periodicUpdate is called it exits. Why this happen?! I tried changing the syntax, putting sys.exit in an other function and call that function, i tried other solutions but always it behave in two ways: it exits or it behave as the timer doesn't exists. Can someone help me? Thanks very much
Remove the parentheses. If you use sys.exit(), it will fire straight away. When you use sys.exit, it will pass the function as Timer's second argument.
I think your approach is not the best one, instead of running a timer that exits the application, why not simply timeout the function that reads the data:
Timeout on a function call
It seems that it reads sys.exit() before all the rest
Sure it does. The second argument of threadint.Timer is a function that will be called. What you do is you actually call sys.exit and supply its return value (which is undefined, by the way, since the call terminates the program) as a function to be called. That's an error, since sys.exit's return value is not a function, but that doesn't matter, as the program is terminated anyway.
What you want to do is
exitTimer = threading.Timer(60.0, sys.exit) # note: no brackets
But that actually will not work, as sys.exit in the thread will terminate only that thread. In short, you can't use a watchdog to terminate a stuck while-loop if this loops is in your main thread. In your particular situation you should investigate the function you are using to read data, most likely it lets you set a read timeout.
It seems to me that none of the solutions proposed here actually works. This is an example of code. Would be great to know how to fix it. Also, please try it before answering.
import time, threading, sys
def _exit():
print 'exiting'
sys.exit()
def periodicUpdate():
exitTimer = threading.Timer(2.0, _exit)
while True:
exitTimer.start()
print 'go'
time.sleep(5)
exitTimer.cancel()
periodicUpdate()
The actual output is:
$python test.py
go
exiting
RuntimeError: threads can only be started once
exitTimer = threading.Timer(60.0, sys.exit)
Remove the () from sys.exit in timer call
def _exit()
sys.exit()
def periodicUpdate():
exitTimer = threading.Timer(60.0, _exit)
while True:
exitTimer.start()
readData()
exitTimer.cancel()
In you put the () the interpreter call this function if not the interpreter get a reference for this function.
Have fun :)
Edit: Use of _exit
threading.Timer(60.0, os._exit, [0])
def periodicUpdate():
exitTimer = sys.exit(60.0, sys.exit())
while sys.exit():
sys.exit()
readData()
sys.exit()
if __name__ == "__main__":
sys.exit()
Don't forget to import sys.
Since there is no goto operator in Python, what technique can be used instead?
Condition
If it is true, go to thread 1, if is false, go to thread 2
In thread we do something small and after that we go to thread 2 where all other actions take place.
Since there is no goto operator in Python, what technique can be used instead?
Constructing your code logically and semantically.
if condition:
perform_some_action()
perform_other_actions()
def thread_1():
# Do thread_1 type stuff here.
def thread_2():
# Do thread_2 type stuff here.
if condition:
thread_1()
# If condition was false, just run thread_2().
# If it was true then thread_1() will return to this point.
thread_2()
edit: I'm assuming that by "thread" you mean a piece of code (otherwise known as a subroutine or a function). If you're talking about threads as in parallel execution then you'll need more detail in the question.
To the best of my knowledge it's not present (thankfully), but you should check this link
The "goto" module was an April Fool's joke, published on 1st April
2004. Yes, it works, but it's a joke nevertheless. Please don't use it in real code!
Python is designed to support good coding practices and GOTO is not one of them. It may lead to unreadable program logic, if not used properly.
I suggest to learn code your program in a Python way, do not stick with (sometimes bad) habits from other programming languages. See Python documentation, real mature Python programs and learn.
def thread1():
#write your thread 1 code here
print("entered no is 1")
def thread2():
#write your thread 2 code here
print("Number is greater or less then one.")
def main():
a=input()
if a==1:
thread1()
elif a<=1 or a>=1:
thread2()
#you can use recursion here in case if you want to use agin and again
#if you want to print serveral time you can use looping.
for i in range(4):
main()
#if you want to run goto forever and ever and ever then remove loop in
#this code.
#this code will enable you the equivalent of goto statement.
This is what I use every time in Python 3.x.