I found out that threading module in python 3.6 is not working properly.
problem is :
thread starts running before I call whatsoever_thread_name.start().
also, the code would not go to the next step from where I declare the first thread object in my code
Example :
import threading
def a():
while(1):
print(1)
def b():
while(1):
print(222)
t = threading.Thread(target = a())
v = threading.Thread(target = b())
result :
1
1
1
1
1
1
1
1
... infinitely
You need to assign the callback to target. Do not call the functions with ():
t = threading.Thread(target=a)
v = threading.Thread(target=b)
The threads will run these functions for you. The () means you are calling them yourself and attempting to assign the return value to target, but these functions don't return because they run forever.
Related
I am trying to code an alarm in python that has 6 functions that need to multithread. 5 of these are alarms and one of them displays the time. The threads need to start and stop whenever the menu option is selected and when the alarm rings. The Display thread is the only thread that keeps going until the program stops. My current code for the alarm looks like this (I've removed a lot for the sake of clarity)
class TAlarm1 (threading.Thread):
def Alarm1():
while True:
#code which keeps running until the time is equal to the input given (expected to thread)
thread1 = threading.Thread(target=TAlarm1)
thread1.start()
def AlarmSelector():
print("Select an Alarm") #5 alarms will be added however each one accomplishes the same task. all of them need to run simultaneously
choice = int(input())
if choice == 1:
ala = TAlarm1()
ala.Alarm1()
if choice == 6:
DisplayTime() #goes back to displaying time
Whenever I run this code, the program displays no errors however it does not run the code in TAlarm1().
How can I solve this problem?
While your intent isn't clear to me. Here is how you can subclass Thread with its run method overridden and start it conditionally.
import threading
class TAlarm1 (threading.Thread):
def run(self):
n =4
while True:
#code which keeps running until the time is equal to the input given (expected to thread)
print(n,end=' | ')
n -= 1
if n < 0:
break
print()
t1 = TAlarm1()
if True:
t1.start()
A thread can only be started once so you have to make a new one every time you need it to run.
>>> t = TAlarm1()
>>> t.start()
4 | 3 | 2 | 1 | 0 |
>>> t.start()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python38\lib\threading.py", line 848, in start
raise RuntimeError("threads can only be started once")
RuntimeError: threads can only be started once
>>> t = TAlarm1()
>>> t.start()
4 | 3 | 2 | 1 | 0 |
>>>
The target parameter of Thread takes a callable. A class is a callable, but calling it just creates an instance of the class. Pass it a function instead:
import threading
def Alarm1():
print('Alarm1 called')
thread1 = threading.Thread(target=Alarm1)
thread1.start()
There are two basic ways of implementing threaded code in Python. You seem to have half of each.
The first implementation model is to put the logic to run in the thread into a function, then pass that function as the target argument when you create a threading.Thread instance:
import threading
import time
def worker(n):
for i in range(n):
print(i)
time.sleep(0.5)
my_thread = threading.Thread(target=worker, args=(10,))
my_thread.start()
# do other stuff in the main thread, if desired
my_thread.join()
The other implementation approach is to subclass threading.Thread and put the code to be run in the thread inside of the run method (or in other methods called from run). This is especially useful if your thread code has some complicated state and you want to be able to use additional methods to manipulate that state while the thread is running:
class MyThread(threading.Thread):
def __init__(self, n):
super().__init__()
self.n = n
self.unpaused = threading.Event()
self.unpaused.set() # we start unpaused
def run(self):
for i in range(self.n):
self.unpaused.wait() # block if we're paused
print(i)
time.sleep(0.5)
def pause(self):
self.unpaused.clear()
def unpause(self):
self.unpaused.set()
my_thread = MyThread(10)
my_thread.start()
# an example of inter-thread communication, we pause and unpause our thread using its methods
time.sleep(2)
my_thread.pause()
time.sleep(2)
my_thread.unpause()
my_thread.join()
I want to move some functions to an external file for making it clearer.
lets say i have this example code (which does indeed work):
import threading
from time import sleep
testVal = 0
def testFunc():
while True:
global testVal
sleep(1)
testVal = testVal + 1
print(testVal)
t = threading.Thread(target=testFunc, args=())
t.daemon = True
t.start()
try:
while True:
sleep(2)
print('testval = ' + str(testVal))
except KeyboardInterrupt:
pass
now i want to move testFunc() to a new python file. My guess was the following but the global variables don't seem to be the same.
testserver.py:
import threading
import testclient
from time import sleep
testVal = 0
t = threading.Thread(target=testclient.testFunc, args=())
t.daemon = True
t.start()
try:
while True:
sleep(2)
print('testval = ' + str(testVal))
except KeyboardInterrupt:
pass
and testclient.py:
from time import sleep
from testserver import testVal as val
def testFunc():
while True:
global val
sleep(1)
val = val + 1
print(val)
my output is:
1
testval = 0
2
3
testval = 0 (testval didn't change)
...
while it should:
1
testval = 1
2
3
testval = 3
...
any suggestions? Thanks!
Your immediate problem is not due to multithreading (we'll get to that) but due to how you use global variables. The thing is, when you use this:
from testserver import testVal as val
You're essentially doing this:
import testserver
val = testserver.testVal
i.e. you're creating a local reference val that points to the testserver.testVal value. This is all fine and dandy when you read it (the first time at least) but when you try to assign its value in your function with:
val = val + 1
You're actually re-assigning the local (to testclient.py) val variable, not setting the value of testserver.testVal. You have to directly reference the actual pointer (i.e. testserver.testVal += 1) if you want to change its value.
That being said, the next problem you might encounter might stem directly from multithreading - you can encounter a race-condition oddity where GIL pauses one thread right after reading the value, but before actually writing it, and the next thread reading it and overwriting the current value, then the first thread resumes and writes the same value resulting in single increase despite two calls. You need to use some sort of mutex to make sure that all non-atomic operations execute exclusively to one thread if you want to use your data this way. The easiest way to do it is with a Lock that comes with the threading module:
testserver.py:
# ...
testVal = 0
testValLock = threading.Lock()
# ...
testclient.py:
# ...
with testserver.testValLock:
testserver.testVal += 1
# ...
A third and final problem you might encounter is a circular dependency (testserver.py requires testclient.py, which requires testserver.py) and I'd advise you to re-think the way you want to approach this problem. If all you want is a common global store - create it separately from modules that might depend on it. That way you ensure proper loading and initializing order without the danger of unresolveable circular dependencies.
I have some Python code that look this:
from ltpd import *
def thread_function():
for i in range(5):
if activatewindow('Confirm New Extension'):
generatekeyevent('<left><space>')
break
time.sleep(1)
def main():
for i in range some_big_range:
thread = Thread(target = thread_function)
thread.start()
# Code that runs for really long time
I was expecting for a new thread to be created for every i in the loop. However, the thread is being created only once. I need the thread to be started freshly for every iteration of the for loop. Can anyone tell me what's wrong and how to fix it?
Every iteration a new thread is startet:
>>> from threading import Thread
>>> def fun(cnt):
... print cnt
...
>>> for i in range(5):
... thread = Thread(target=fun, args=(i,))
... thread.start()
...
0
1
2
3
>>> 4
In my first project with serial communication I am trying to implement a procedure where a function in a background thread listens on the serial port for a ready signal. When a ready signal is received it updates a global variable to a True value so that another function will start.
Below is a simplified version of the logic, but I cant get it to work. Instead of running concurrently the two threads it seems like it is still running consecutively
import threading
import time
global CONS
CONS = False
print(CONS)
def timeout(state,my_timeout):
_time = 0
while _time < my_timeout:
if state:
print(state)
print('Signal received, returning True to start another function')
return bool(state)
_time += 1
time.sleep(1)
print(_time)
else:
print('Timeout occured: Ready signal not received within %s seconds', _time)
return False
def smallmeth():
time.sleep(2)
global CONS
CONS = True
print(CONS)
return CONS
t1 = threading.Thread(target=timeout(CONS,5))
t2 = threading.Thread(target=smallmeth)
threading.enumerate()
# t1.setDaemon()
t1.start()
t2.start()
The output I get when running this is this:
False
1
2
3
4
5
Timeout occured: Ready signal not received within 5 seconds
True
t1 = threading.Thread(target=timeout(CONS,5))
Here you call the function timeout and then you pass the result as target for the new Thread. So timeout is executed before t1 is created. If you want to pass arguments to the thread target, do it like this:
t1 = threading.Thread(target=timeout, args=(CONS,5))
Also you never use the global variable in timeout. So the result will still be the same even after you make the correction mentioned above.
I have recently posted a question about how to postpone execution of a function in Python (kind of equivalent to Javascript setTimeout) and it turns out to be a simple task using threading.Timer (well, simple as long as the function does not share state with other code, but that would create problems in any event-driven environment).
Now I am trying to do better and emulate setInterval. For those who are not familiar with Javascript, setInterval allows to repeat a call to a function every x seconds, without blocking the execution of other code. I have created this example decorator:
import time, threading
def setInterval(interval, times = -1):
# This will be the actual decorator,
# with fixed interval and times parameter
def outer_wrap(function):
# This will be the function to be
# called
def wrap(*args, **kwargs):
# This is another function to be executed
# in a different thread to simulate setInterval
def inner_wrap():
i = 0
while i != times:
time.sleep(interval)
function(*args, **kwargs)
i += 1
threading.Timer(0, inner_wrap).start()
return wrap
return outer_wrap
to be used as follows
#setInterval(1, 3)
def foo(a):
print(a)
foo('bar')
# Will print 'bar' 3 times with 1 second delays
and it seems to me it is working fine. My problem is that
it seems overly complicated, and I fear I may have missed a simpler/better mechanism
the decorator can be called without the second parameter, in which case it will go on forever. When I say foreover, I mean forever - even calling sys.exit() from the main thread will not stop it, nor will hitting Ctrl+c. The only way to stop it is to kill python process from the outside. I would like to be able to send a signal from the main thread that would stop the callback. But I am a beginner with threads - how can I communicate between them?
EDIT In case anyone wonders, this is the final version of the decorator, thanks to the help of jd
import threading
def setInterval(interval, times = -1):
# This will be the actual decorator,
# with fixed interval and times parameter
def outer_wrap(function):
# This will be the function to be
# called
def wrap(*args, **kwargs):
stop = threading.Event()
# This is another function to be executed
# in a different thread to simulate setInterval
def inner_wrap():
i = 0
while i != times and not stop.isSet():
stop.wait(interval)
function(*args, **kwargs)
i += 1
t = threading.Timer(0, inner_wrap)
t.daemon = True
t.start()
return stop
return wrap
return outer_wrap
It can be used with a fixed amount of repetitions as above
#setInterval(1, 3)
def foo(a):
print(a)
foo('bar')
# Will print 'bar' 3 times with 1 second delays
or can be left to run until it receives a stop signal
import time
#setInterval(1)
def foo(a):
print(a)
stopper = foo('bar')
time.sleep(5)
stopper.set()
# It will stop here, after printing 'bar' 5 times.
Your solution looks fine to me.
There are several ways to communicate with threads. To order a thread to stop, you can use threading.Event(), which has a wait() method that you can use instead of time.sleep().
stop_event = threading.Event()
...
stop_event.wait(1.)
if stop_event.isSet():
return
...
For your thread to exit when the program is terminated, set its daemon attribute to True before calling start(). This applies to Timer() objects as well because they subclass threading.Thread. See http://docs.python.org/library/threading.html#threading.Thread.daemon
Maybe these are the easiest setInterval equivalent in python:
import threading
def set_interval(func, sec):
def func_wrapper():
set_interval(func, sec)
func()
t = threading.Timer(sec, func_wrapper)
t.start()
return t
Maybe a bit simpler is to use recursive calls to Timer:
from threading import Timer
import atexit
class Repeat(object):
count = 0
#staticmethod
def repeat(rep, delay, func):
"repeat func rep times with a delay given in seconds"
if Repeat.count < rep:
# call func, you might want to add args here
func()
Repeat.count += 1
# setup a timer which calls repeat recursively
# again, if you need args for func, you have to add them here
timer = Timer(delay, Repeat.repeat, (rep, delay, func))
# register timer.cancel to stop the timer when you exit the interpreter
atexit.register(timer.cancel)
timer.start()
def foo():
print "bar"
Repeat.repeat(3,2,foo)
atexit allows to signal stopping with CTRL-C.
this class Interval
class ali:
def __init__(self):
self.sure = True;
def aliv(self,func,san):
print "ali naber";
self.setInterVal(func, san);
def setInterVal(self,func, san):
# istenilen saniye veya dakika aralığında program calışır.
def func_Calistir():
func(func,san); #calışıcak fonksiyon.
self.t = threading.Timer(san, func_Calistir)
self.t.start()
return self.t
a = ali();
a.setInterVal(a.aliv,5);