My main script launches an API and another thread executes a daily task to update data.
Currently, the daily update can change data during an API call and it will cause an error.
I think my problem can be summarized as the following code :
import schedule
from threading import Thread, Lock
import time
def periodically_run_pending_tasks(interval=0.5):
while True:
schedule.run_pending()
time.sleep(interval)
def change_state(item):
item.a = "New state"
class MyClass:
def __init__(self):
self.a = "Initial state"
def print_state_twice(self, lk):
lk.acquire()
print(self.a)
time.sleep(2)
print(self.a)
lk.release()
my_class = MyClass()
lock = Lock()
thread = Thread(target=periodically_run_pending_tasks)
schedule.every().second.do(change_state, my_class)
thread.start()
my_class.print_state_twice(lock)
I want this script to output either twice Initial state or twice New state but it returns Initial State New state.
I've also tried :
import schedule
from threading import Thread, Lock
import time
def periodically_run_pending_tasks(interval=0.5):
while True:
schedule.run_pending()
time.sleep(interval)
def change_state(item):
item.a = "New state"
class MyClass:
def __init__(self):
self.a = "Initial state"
def print_state_twice(self, lk):
lk.acquire()
print(self.a)
time.sleep(2)
print(self.a)
lk.release()
my_class = MyClass()
lock = Lock()
thread_2 = Thread(target=my_class.print_state_twice, args=(lock,))
thread_2.start()
thread = Thread(target=periodically_run_pending_tasks)
schedule.every().second.do(change_state, my_class)
thread.start()
Related
I try to run a thread that is calculating different data and when the server call is made to serve data.
What i do not understand is why the program not pass to call sending and receiving after thread start
class FuncThread(threading.Thread):
def __init__(self, image_model):
self.image_model = image_model
threading.Thread.__init__(self)
def run(self):
image_model = self.image_model
while True:
def sending_ receiving():
while true:
image_model = init()
thread1 = FuncThread(image_model)
thread1.setDaemon(True)
thread1.start() # this should not affect the course of executing order
sending_and_reciveing() - this is contiuously listening client request
thread.start is calling run method that is a while true loop that run continuously .
if I correct the typos in your code, it works well on my machine.
import time
import threading
class FuncThread(threading.Thread):
def __init__(self, image_model):
self.image_model = image_model
threading.Thread.__init__(self)
def run(self):
image_model = self.image_model
while True:
print('run')
time.sleep(1)
def sending_and_receiving():
while True:
print('sending_and_receiving')
time.sleep(1)
image_model = 'test'
thread1 = FuncThread(image_model)
thread1.setDaemon(True)
thread1.start()
sending_and_receiving()
I have been searching for some explanations about thread synchronization. I have found a challenge to use as case of study, I will simply here with my solution. Basically there is a class with a numeric value, and you can add or subtract from it. If there is many threads accessing this instance, it should wait all threads finishes before return the final value. My implementation is the following:
from threading import Lock, Thread
from time import sleep
import sys
class ClassA(object):
def with_lock():
def wrapper(func):
def wrapped(self, *args):
with self.lock:
return func(self, *args)
return wrapped
return wrapper
def __init__(self, balance = 0):
self.balance = balance
self.lock = Lock()
def get_balance(self):
return self.balance
#with_lock()
def add(self):
self.balance += 1
#with_lock()
def sub(self):
self.balance -= 1
if __name__ == "__main__":
sys.setswitchinterval(1e-12)
value = 10
def foo():
a.add()
sleep(0.01)
a.sub()
a = ClassA(value)
threads = [Thread(target=foo) for _ in range(1000)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
print(a.get_balance()) # should return "value"
The implementation of the decorator "with_lock" was found in other implementation from the internet, but I did not understand it.
About this part:
with self.lock:
return func(self, *args)
I have searched about the Lock documentation, and it shows that self.lock would be a Lock Object with methods acquire and release. Can I understand the 'with' statement would wait until the thread is released? Or is there any other behavior?
The print at the end waits until all the threads to finish, but the get_balance does not have the decorator "with_lock". Why it waits until the threads finish?
I created two threads each running different functions.
What i tryed to achieve is if first thread ends then the second should also end ( i tryed achieving it using global variable)
Once both the threads end the same procedure should continue.
The script is not working as expected.
I am using Linux - Centos and python 2.7
#!/usr/bin/python
import threading
import time
import subprocess
import datetime
import os
import thread
command= "strace -o /root/Desktop/a.txt -c ./server"
final_dir = "/root/Desktop/"
exitflag = 0
# Define a function for the thread
def print_time(*args):
os.chdir(final_dir)
print "IN first thread"
proc = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc.wait(70)
exitflag=1
def print_time1(*args):
print "In second thread"
global exitflag
while exitflag:
thread.exit()
#proc = subprocess.Popen(command1,shell=True,stdout=subprocess.PIPE, sterr=subprocess.PIPE)
# Create two threads as follows
while (1):
t1=threading.Thread(target=print_time)
t1.start()
t2=threading.Thread(target=print_time1)
t2=start()
time.sleep(80)
z = t1.isAlive()
z1 = t2.isAlive()
if z:
z.exit()
if z1:
z1.exit()
threading.Thread(target=print_time1).start()
threading.Thread(target=print_time1).start()
print "In try"
Where am i going wrong?
You could create an object to share state, and have the dependent thread check that state. Something like:
import threading
import time
import datetime
class Worker1( threading.Thread ):
def __init__(self, state):
super(Worker1, self).__init__()
self.state = state
def run(self):
print_time_helper("Worker1 Start")
time.sleep(4)
print_time_helper("Worker1 End")
self.state.keepOnRunning = False
class Worker2( threading.Thread ):
def __init__(self, state):
super(Worker2, self).__init__()
self.state = state
def run(self):
while self.state.keepOnRunning:
print_time_helper("Worker2")
time.sleep(1)
class State( object ):
def __init__(self):
self.keepOnRunning = True
def main():
state = State()
thread1 = Worker1(state)
thread2 = Worker2(state)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
def print_time_helper(name):
print "{0}: {1}".format(name, datetime.datetime.now().time().strftime("%S"))
which will output something like this (numbers show current time seconds):
Worker1 Start: 39
Worker2: 39
Worker2: 40
Worker2: 41
Worker2: 42
Worker1 End: 43
However, this is a bit simplistic for most situations. You might be better off using message queues - this is a good intro.
Use a threading.Event instead of an int and wait for it to be set.
Also your logic appears to be wrong in print_time1 because your while loop will never run since exitflag is initially 0, but even if it was 1 it would still just exit immediately. It's not actually waiting on anything.
I want two objects of the same class to operate concurrently. The class "MyClass" has a function that connects an instance to another instance of the class. I also need to keep track of the objects that have been created (oList). what I am trying is:
main.py:
from MyClass import MyClass
import time
oList = []
class oCreator1(Thread):
def __init__(self):
Thread.__init__(self)
self.o1 = MyClass()
def run(self):
while 1:
time.sleep(1)
print "Hi"
def getO1(self):
return self.o1
class oCreator2(Thread):
def __init__(self):
Thread.__init__(self)
self.o2 = MyClass()
def run(self):
while 1:
time.sleep(1)
print "Bye!"
def getO2(self):
return self.o2
main():
threadList = []
global oList
oc1 = oCreator1()
threadList.append(oc1)
o1 = oc1.getO1()
oList.append(o1)
oc2 = oCreator2()
threadList.append(oc2)
o2 = oc2.getO2()
oList.append(o2)
o1.connToAnotherO(o2)
print oList
for t in threadList:
t.start()
t.join()
if __name__ == '__main__':
main()
But the only thing that is printed is "Hi". I really want to know the things I'm doing wrong and the right way to do it. Thank you in advance.
for t in threadList:
t.start()
t.join()
The t.join() call waits for the thread t to finish. That means when you start the first thread, you wait for it to finish before starting the second, but the first thread is just going to keep printing Hi forever. It'll never finish.
Don't join, or don't start joining until all threads have started.
Having class which has a long method.
Creating a thread for that method.
How i can kill\terminate this thread?
Main problem is that i can't check for threading.Event in thread run() method because it doesn't contain loop.
Similar code as here:
import time
import threading
class LongAction:
def time_consuming_action(self):
tmax = 600
for i in range(tmax):
print i
time.sleep(1)
time.sleep(tmax)
self.tmax = tmax
return "Slept well"
class LongActionThread(threading.Thread):
def __init__(self, la_object):
self.la = la_object
threading.Thread.__init__(self)
def run(self):
self.la.time_consuming_action()
la = LongAction()
la_thread = LongActionThread(la)
la_thread.start()
# After 5 sec i've changed my mind and trying to kill LongActionThread
time.sleep(5)
print "Trying to kill LongActionThread"
la_thread.kill()
This code works fine but there is a need to explicitly flush data from standard output.
Haven't found a way where prints would work without flushing.
import time
from multiprocessing.process import Process
import sys
class LongAction:
def time_consuming_action(self):
tmax = 600
for i in range(tmax):
print i
time.sleep(1)
sys.stdout.flush()
time.sleep(tmax)
self.tmax = tmax
return "Slept well"
sys.stdout.flush()
class LongActionThread(Process):
def __init__(self, la_object):
self.la = la_object
Process.__init__(self)
def run(self):
self.la.time_consuming_action()
if __name__ == "__main__":
la = LongAction()
la_thread = LongActionThread(la)
la_thread.start()
# After 5 sec i've changed my mind and trying to kill LongActionThread
time.sleep(5)
print "Trying to kill LongActionThread"
la_thread.terminate()
While it is not a good idea to kill a thread, if you really must do it, the easiest solution is to implement a running semaphor, divide your time consuming method in sub_methods and check for thread status between the submethods.
Code partly copied from this SO question:
class StoppableThread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""
def __init__(self,la_object):
super(StoppableThread, self).__init__()
self.la = la_object
self._stop = threading.Event()
def stop(self):
self._stop.set()
def stopped(self):
return self._stop.isSet()
def run(self):
self.la.time_consuming_action( self.stopped )
class La :
def __init__(self):
#init here
def time_consuming_action(self, thread_stop_callback ):
sub_work1()
if thread_stop_callback():
raise 'Thread Killed ! '
sub_work2()
if thread_stop_callback():
raise 'Thread Killed ! '
sub_work3()
#etc...