Python thread in while loop - python

I want test_func to work separately. It should print every N seconds, I've tried this, but time.sleep() just stops my program.
import time
import threading
def test_func():
time.sleep(10)
print("Printing stuff....")
t = threading.Timer(10, test_func).start()
test_func()
# something goes here constantly
So I though of doing something like this, but that doesn't work either.
import time
import threading
def test_func():
time.sleep(10)
print("Printing stuff....")
# something goes here constantly
while True:
t = threading.Timer(10, test_func).start()
So, how can it be fixed?

You don't need a timer for this. Just put your function in a thread, so:
def test_func():
while True:
print("Printing stuff....")
time.sleep(10)
threading.Thread(target=test_func).start()

Do not span more threads within while loop. Instead change code to
def test_func():
while True:
time.sleep(10)
print("Printing stuff....")
Call the test_func() here in thread.

Related

How can I make a function run in the background without blocking my entire program?

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())

Python threading a subfunction

My application is running a in a loop.. sometimes it needs to call a led flash function from the loop. I pretty much did that like this;
def led_red_flash(flashcount):
logging.debug('Starting')
for l in range(0,flashcount):
GPIO.output(16,GPIO.HIGH)
time.sleep(0.1)
GPIO.output(16,GPIO.LOW)
time.sleep(0.1)
logging.debug('Stopping')
while True:
<do some stuff here>
t = threading.Thread(name='led_red_flash', target=led_red_flash(100) )
t.start()
This works.. but would there be a day to put all the threading stuff in the def led_red_flash part? As my scripts gets more complex it will make it harder to read. So something like this;
while True:
<do some stuff here>
led_red_flash(100)
The above is a very simplified version of the loop I am running. In the actual script it would not be possible to have multiple instances of led_red_flash run at the same time.. so this is not an issue.
You can create a wrapper function:
def _led_red_flash(flashcount):
logging.debug('Starting')
for l in range(0,flashcount):
GPIO.output(16,GPIO.HIGH)
time.sleep(0.1)
GPIO.output(16,GPIO.LOW)
time.sleep(0.1)
logging.debug('Stopping')
def led_red_flash(flashcount):
t = threading.Thread(name='led_red_flash', target=_led_red_flash, args=(100,))
t.start()
return t
BTW, your original code didn't execute led_red_flash in a separate thread. I justed called led_red_flash (led_red_flash(100)).
You should pass the function itself, not the return value of the function call. See threading.Thread.
threading.Thread(name='led_red_flash', target=led_red_flash(100))
to
threading.Thread(name='led_red_flash', target=led_red_flash, args=(100,))

Python threading.Timer not waiting before executing function

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')

Running a background thread in python

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()

Different way to implement this threading?

I'm trying out threads in python. I want a spinning cursor to display while another method runs (for 5-10 mins). I've done out some code but am wondering is this how you would do it? i don't like to use globals, so I assume there is a better way?
c = True
def b():
for j in itertools.cycle('/-\|'):
if (c == True):
sys.stdout.write(j)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')
else:
return
def a():
global c
#code does stuff here for 5-10 minutes
#simulate with sleep
time.sleep(2)
c = False
Thread(target = a).start()
Thread(target = b).start()
EDIT:
Another issue now is that when the processing ends the last element of the spinning cursor is still on screen. so something like \ is printed.
You could use events:
http://docs.python.org/2/library/threading.html
I tested this and it works. It also keeps everything in sync. You should avoid changing/reading the same variables in different threads without synchronizing them.
#!/usr/bin/python
from threading import Thread
from threading import Event
import time
import itertools
import sys
def b(event):
for j in itertools.cycle('/-\|'):
if not event.is_set():
sys.stdout.write(j)
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')
else:
return
def a(event):
#code does stuff here for 5-10 minutes
#simulate with sleep
time.sleep(2)
event.set()
def main():
c = Event()
Thread(target = a, kwargs = {'event': c}).start()
Thread(target = b, kwargs = {'event': c}).start()
if __name__ == "__main__":
main()
Related to 'kwargs', from Python docs (URL in the beginning of the post):
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
...
kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.
You're on the right track mostly, except for the global variable. Normally you'd needed to coordinate access to shared data like that with a lock or semaphore, but in this special case you can take a short-cut and just use whether one of the threads is running or not instead. This is what I mean:
from threading import Thread
from threading import Event
import time
import itertools
import sys
def monitor_thread(watched_thread):
chars = itertools.cycle('/-\|')
while watched_thread.is_alive():
sys.stdout.write(chars.next())
sys.stdout.flush()
time.sleep(0.1)
sys.stdout.write('\b')
def worker_thread():
# code does stuff here - simulated with sleep
time.sleep(2)
if __name__ == "__main__":
watched_thread = Thread(target=worker_thread)
watched_thread.start()
Thread(target=monitor_thread, args=(watched_thread,)).start()
This is not properly synchronized. But I will not try to explain it all to you right now because it's a whole lot of knowledge. Try to read this: http://effbot.org/zone/thread-synchronization.htm
But in your case it's not that bad that things aren't synchronized correctyl. The only thing that could happen, is that the spining bar spins a few ms longer than the background task actually needs.

Categories

Resources