I want to run a function every few seconds in Python. The function execution takes some time, and I want to include that in the waiting time as well.
I don't want to do this, because it is not strictly executed every 2 seconds and will break the periodicity (my_function also takes time to execute.)
while True:
time.sleep(2)
my_function()
I don't want to do this neither, because it uses too much CPU on the while loop of Thread-2.
# Thread-1
While True:
time.sleep(2)
event.set()
# Thread-2
While True:
if event.is_set():
my_function()
else:
pass
Can anyone please help me?
You can consider ischedule. It takes care of the function execution time right out the box, and doesn't waste CPU time for busy waiting. You can use:
from ischedule import schedule, run_loop
schedule(my_function, interval=2)
run_loop()
I believe the schedule module is your friend
I found this code works pretty well, if I understood your question correctly.
Code broken down:
runs func1
runs func2
waits 2s
does something else after that
waits 1s
does it all again
import threading
import time
def func1():
print("function 1 has been called")
def func2():
print("function 2 has been called")
def loop():
print("loop print 1")
thread = threading.Thread(target=func1, name="thread")
thread.start()
while thread.is_alive():
continue
if not thread.is_alive():
thread2 = threading.Thread(target=func2, name="thread2")
thread2.start()
while thread2.is_alive():
continue
time.sleep(2)
while True:
loop()
print("Some other thing")
time.sleep(1)
Related
I have a loop which makes a get request to a webservice to fetch data and do some stuff, but I want to 'manually' terminate the thread/event, which I achieved with the following example:
from threading import Event
exit = Event()
if external_condition():
exit.set()
for _ in range(mins):
fetch_data_and_do_stuff()
exit.wait(10) #wait 10 seconds
With that, the only thing that terminates it's the sleep time between loops. How can I also kill the loop so it doesn't keep running until it gets to the last iteration?
nvm i've solved it like this
from threading import Event
exit = Event()
if external_condition():
exit.set()
for _ in range(mins):
fetch_data_and_do_stuff()
if exit.wait(10):
break
the condition returns true when killed and also sleeps the 10 seconds, so it works
you have 2 options ,
kill the thread or process entirely
or making the loop's boolean false. going that way
you could use a global variable in this way: [Python 3.7] , run it to see
from threading import Thread
from time import sleep
global glob
glob=True
def threaded_function():
while glob:
print("\n [Thread] this thread is running until main function halts this")
sleep(0.8)
if __name__ == "__main__":
thread = Thread(target = threaded_function, args = ())
thread.start()
for i in range(4,0,-1):
print("\n [Main] thread will be terminated in "+str(i)+" seconds")
sleep(1)
glob=False
while True:
print("[Main] program is over")
sleep(1)
I have some difficulties into making this function running in the background without blocking my entire program, how can I run that function in loop, without blocking my entire program?
This is the function:
while True:
schedule.run_pending()
Thank you for any reply.
Edit:
def FunctioninLoop():
while True:
schedule.run_pending()
async def MyFunction():
ScheduleToexecute=schedule.every().minute.do(Functionscheduled)
t = Thread(target=FunctioninLoop())
t.start()
print("The execution is going on")
Threads are what you are looking for.
Consider the following code:
from threading import Thread
def myfunc(a, b, c):
pass
# Creates a thread
t = Thread(target=myfunc, args=(1, 2, 3))
# Launches the thread (while not blocking the main execution)
t.start()
somecode
somecode
somecode
# Waits for the thread to return (not a must)
t.join()
Hope I've helped! :)
import threading
pender = threading.thread(schedule.run_pending) # Does not Block
print("life goes on until...")
pender.join() # Blocks until schedule.run_pending() is complete.
You can use python's subprocess module
https://docs.python.org/3.2/library/subprocess.html
import os
def myfunction():
..........
os.spawnl(os.P_NOWAIT, myfunction())
The following code:
import threading
import time
from functools import partial
from itertools import count
def daemon_loop(sleep_interval, stop_event):
for j in count():
print(j)
if stop_event.is_set():
break
time.sleep(sleep_interval)
print('Slept %s' % sleep_interval)
print('Prod terminating')
if __name__ == '__main__':
stop_event = threading.Event() #https://stackoverflow.com/a/41139707/281545
target = partial(daemon_loop, sleep_interval=2, stop_event=stop_event)
prod_thread = threading.Thread(target=target,
# daemon=True
)
try:
prod_thread.start()
while True:
time.sleep(10)
except KeyboardInterrupt:
print('Terminating...')
stop_event.set()
prints on a keyboard interrupt:
C:\Users\MrD\.PyCharm2018.2\config\scratches>c:\_\Python363-64\python.exe thread_daemon.py
0
Slept 2
1
Terminating...
Slept 2
2
Prod terminating
Uncommenting the # daemon=True line results in the prod_thread being ended immediately:
C:\Users\MrD\.PyCharm2018.2\config\scratches>c:\_\Python363-64\python.exe thread_daemon.py
0
Slept 2
1
Terminating...
My question is what is the preferred/more pythonic way to deal with thread termination - should I drop the Event machinery and just mark the thread as daemon or is there some edge case I miss?
See:
Daemon Threads Explanation
How to stop daemon thread?
I haven't done enough Python to give you a "Pythonic" answer, but I can answer in more general programming terms.
Firstly, I'm not a fan of terminating threads. There are cases where it is safe and OK, such as your example here - but terminating in the middle of print writing its output would feel a little dirty.
Secondly, if you want to continue using sleep (which I'm also not a fan of) you could repeat your if stop_event.is_set(): and break after the sleep. (Don't move the code, copy it.) The main problem with sleep in this case is that it will wait the full sleep_interval even if the event is set during that time.
Thirdly - and my preference - instead of using sleep, do a wait on the event with a timeout. If the event is not set during the wait, wait returns false after waiting the timeout period. If the event is set before or during the wait, wait returns true immediately (that is, it aborts the timeout, giving you fast, clean shutdown of the thread.)
So your code would look something like this:
def daemon_loop(sleep_interval, stop_event):
for j in count():
print(j)
if stop_event.wait(sleep_interval):
break
print('Slept %s' % sleep_interval)
print('Prod terminating')
I have thrown together a quick threading test:
import threading
def test():
print "it don't work"
while True:
threading.Timer(1, test).start()
It runs test, but it doesn't wait. What's wrong?
In each loop iteration, you start a new thread. Therefore you will reach the limit of allowed thread and you will get an exception : can't start new thread.
while True:
threading.Timer(1, test).start()
You can add global flag and wait until the function is executed - You should use time.sleep to avoid busy waiting.
a = False
def test():
global a
print("hallo")
a = True
threading.Timer(10, test).start()
while not a:
time.sleep(1)
print('done')
All the examples I've been able to get to don't really address my problem, of having a certain procedure in the background constantly looping, while the rest of the program continues.
Here is a simple example of a method that works, using _thread:
import _thread
import time
def countSeconds():
time.sleep(1)
print("Second")
_thread.start_new(countSeconds, ())
def countTenSeconds():
time.sleep(10)
print("Ten seconds passed")
_thread.start_new(countTenSeconds, ())
_thread.start_new(countSeconds, ())
_thread.start_new(countTenSeconds, ())
Ignoring the obvious fact that we could track the seconds, and just print something different if it's a multiple of ten, how would I go about creating this more efficiently.
In my actual program, the threading seems to be guzzling RAM, I assume from creating multiple instance of the thread. Do I have to "start_new" thread at the end of each procedure?
Thanks for any help.
All the examples I've been able to get to don't really address my problem
Which examples?
This does work for me.
import threading
def f():
import time
time.sleep(1)
print "Function out!"
t1 = threading.Thread(target=f)
print "Starting thread"
t1.start()
time.sleep(0.1)
print "Something done"
t1.join()
print "Thread Done"
You're asking for a repeated thread, I don't get what exactly you need, this might work:
import threading
var = False
def f():
import time
counter = 0
while var:
time.sleep(0.1)
print "Function {} run!".format(counter)
counter+=1
t1 = threading.Thread(target=f)
print "Starting thread"
var = True
t1.start()
time.sleep(3)
print "Something done"
var = False
t1.join()
print "Thread Done"
use the threading.timer to continue launching a new background thread
import threading
import time
def countSeconds():
print("Second")
threading.Timer(1, countSeconds).start()
def countTenSeconds():
print("Ten seconds passed")
threading.Timer(10, countTenSeconds).start()
threading.Timer(1, countSeconds).start()
threading.Timer(10, countTenSeconds).start()