Python multithread loading animation - python

I write this code to obtain a simple loading animation. The animation is executed by a dedicated thread but it does not work, only print a single view when the program ends. I do not see the problem.
import threading
import time
import sys
done = False
class myThread (threading.Thread):
def __init__(self, threadID, name):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
def run(self):
print ("Starting " + self.name)
print_loadbar(self.name)
print ("Exiting " + self.name)
def print_loadbar(threadName):
while True:
if done :
break
sys.stdout.write('\r[--- ]')
sys.stdout.flush()
time.sleep(0.5)
sys.stdout.write('\r[ ---]')
sys.stdout.flush()
time.sleep(0.5)
thread1 = myThread(1, "Thread-1")
thread1.start()
#MAIN THREAD
c=0
while c<10 :
time.sleep(1)
c=c+1
done=True

Related

Is it possible to run 2 threads in the same time continuously in python?

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

Python: How to add new thread after one of threads breaks on error

I'm trying to create loop of threads and so far code is good. But I have problem when thread exits because of some exception.
Now I'm trying to figure out how to start additional thread after one thread exits because of exception. I did browse around but I didn't find any example that would work for this complex code. Any help would be great!
If thread stopped and queue is not empty restart stopped thread and continue with rest of the list.
This is my code:
some_list = [1,2,3,4,5,6,7,8]
exitFlag = 0
class threads():
#staticmethod
def process_data(threadName, q,queueLock):
workQueue = q
while not exitFlag:
queueLock.acquire()
if not workQueue.empty():
data = q.get()
queueLock.release()
print "%s processing %s" % (threadName, data)
else:
queueLock.release()
sleep(1)
def run_threads(self):
threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = some_list
queueLock = threading.Lock()
workQueue = Queue.Queue(1000000)
threads = []
threadID = 1
# Create new threads
for tName in threadList:
thread = myThread(threadID, tName, workQueue,queueLock)
thread.start()
threads.append(thread)
threadID += 1
# Fill the queue
queueLock.acquire()
for word in nameList:
workQueue.put(word)
queueLock.release()
# Wait for queue to empty
while not workQueue.empty():
pass
# Notify threads it's time to exit
global exitFlag
exitFlag = 1
# Wait for all threads to complete
for t in threads:
t.join()
print "Exiting Main Thread"
class myThread (threading.Thread,threads):
def __init__(self, threadID, name, q,queueLock):
self.thread = threading.Thread(target=self.run)
threading.Thread.__init__(self,target=self.run)
self.threadID = threadID
self.queueLock = queueLock
self.name = name
self.q = q
def run(self):
print "Starting " + self.name
threads.process_data(self.name, self.q,self.queueLock)
print "Exiting " + self.name
threads().run_threads()
Something like this should work:
...
# Wait for queue to empty
while not workQueue.empty():
for (i, t) in enumerate(threads):
if not t.is_alive():
print("Recreating thread " + t.name)
thread = myThread(threadID, threadList[i], workQueue,queueLock)
thread.start()
threads[i] = thread
threadID += 1
...
I would advice putting the thread-starting code into some method, as it will now be duplicated and hard to maintain.
The problem here is that you might "loose" the data that was popped from queue by the fatal thread.

Non-blocking way to determine if thread is finished?

I have the following code:
import threading
import time
class TestWorker (threading.Thread):
def __init__(self, threadID, name):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
def run(self):
print "Starting " + self.name
time.sleep(20)
print "Exiting " + self.name
# how do I let the calling thread know it's done?
class TestMain:
def __init__(self):
pass
def do_work(self):
thread = TestWorker(1, "Thread-1")
thread.start()
def do_something_else(self):
print "Something else"
def on_work_done(self):
print "work done"
How can I let the main thread know that the TestWorker has finished (call on_work_done()), without blocking calls to do_something_else() as thread.join() would?
You can give your thread instance an optional callback function to call when it's finished.
Note I added a Lock to prevent concurrent printing (which does block).
print_lock = threading.Lock() # Prevent threads from printing at same time.
class TestWorker(threading.Thread):
def __init__(self, threadID, name, callback=lambda: None):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.callback = callback
def run(self):
with print_lock:
print("Starting " + self.name)
time.sleep(3)
with print_lock:
print("Exiting " + self.name)
self.callback()
class TestMain:
def __init__(self):
self.work_done = False
def do_work(self):
thread = TestWorker(1, "Thread-1", self.on_work_done)
thread.start()
def do_something_else(self):
with print_lock:
print("Something else")
def on_work_done(self):
with print_lock:
print("work done")
self.work_done = True
main = TestMain()
main.do_work()
while not main.work_done:
main.do_something_else()
time.sleep(.5) # do other stuff...
print('Done')
Output:
Starting Thread-1
Something else
Something else
Something else
Something else
Something else
Something else
Exiting Thread-1
work done
Done
import queue
import threading
class SThread(threading.Thread, queue.Queue):
def __init__(self, queue_out: object):
threading.Thread.__init__(self)
queue.Queue.__init__(self)
self.queue_out = queue_out
self.setDaemon(True)
self.start()
def run(self):
print('Thread start')
while True:
cmd = self.get()
if cmd is None:
break # exit thread
self.queue_out.put(cmd['target'](*cmd.get('args', ())), **cmd.get('kwargs', {}))
self.task_done()
print('Thread stop')
def testFn(a):
print('+ %s' % a)
return a
if __name__ == '__main__':
print('main 1')
# init
queue_out = queue.Queue()
thread = SThread(queue_out)
# in
for a in range(5): thread.put(dict(target=testFn, args=(a,)))
thread.put(None)
print('main 2')
# out
while True:
try:
print('- %s' % queue_out.get(timeout=3))
except queue.Empty:
break
print('main 3')
OUT:
main 1
Thread start
main 2
+ 0
+ 1
+ 2
+ 3
+ 4
Thread stop
- 0
- 1
- 2
- 3
- 4
main 3
import threading
dt = {}
threading.Thread(target=dt.update, kwargs=dict(out=123)).start()
while 'out' not in dt:
print('out' in dt)
print(dt)

How to terminate a thread in Python without loop in run method?

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...

Python: Run a progess bar and work simultaneously?

I want to know how to run a progress bar and some other work simultaneously, then when the work is done, stop the progress bar in Python (2.7.x)
import sys, time
def progress_bar():
while True:
for c in ['-','\\','|','/']:
sys.stdout.write('\r' + "Working " + c)
sys.stdout.flush()
time.sleep(0.2)
def work():
*doing hard work*
How would I be able to do something like:
progress_bar() #run in background?
work()
*stop progress bar*
print "\nThe work is done!"
You could run a thread in the background using the threading module. For example:
def run_progress_bar(finished_event):
chars = itertools.cycle(r'-\|/')
while not finished_event.is_set():
sys.stdout.write('\rWorking ' + next(chars))
sys.stdout.flush()
finished_event.wait(0.2)
# somewhere else...
finished_event = threading.Event()
progress_bar_thread = threading.Thread(target=run_progress_bar, args=(finished_event,))
progress_bar_thread.start()
# do stuff
finished_event.set()
progress_bar_thread.join()
You can create a separate thread that displays the progress bar. This could be done as shown in #icktoofay's answer, however I would prefer something like the following implementation which derives a new thread subclass for the task. One advantage to this approach is that everything is self contained in each instance of the new class so you don't need global variables for communications between them and the main thread.
import sys
import threading
import time
class ProgressBarThread(threading.Thread):
def __init__(self, label='Working', delay=0.2):
super(ProgressBarThread, self).__init__()
self.label = label
self.delay = delay # interval between updates
self.running = False
def start(self):
self.running = True
super(ProgressBarThread, self).start()
def run(self):
label = '\r' + self.label + ' '
while self.running:
for c in ('-', '\\', '|', '/'):
sys.stdout.write(label + c)
sys.stdout.flush()
time.sleep(self.delay)
def stop(self):
self.running = False
self.join() # wait for run() method to terminate
sys.stdout.write('\r' + len(self.label)*' ' + '\r') # clean-up
sys.stdout.flush()
def work():
time.sleep(5) # *doing hard work*
pb_thread = ProgressBarThread('Computing')
pb_thread.start()
work()
pb_thread.stop()
print("The work is done!")

Categories

Resources