Main thread stuck in Python Multithreading - python

I have 2 simple functions:
def run(self):
# Make 20 instances of clients and start those
for i in xrange(0,20):
t = threading.Thread(target = self.run_clients_in_seperate_threads())
t.start()
and
def run_clients_in_seperate_threads(self):
print 'inside run_clients_in_seperate_threads'
client_id = self.generate_client_id()
cl = Client(client_id)
cl.start()
Here, the last line: cl.start() is an infinite loop.
I was thinking that the main thread will become free after starting the child threads, and hence will spawn 20 threads in total.
But it seems that the main thread waits after starting the 1st thread.
Can someone please explain what I'm doing wrong ?

Use target = self.run_clients_in_seperate_threads and pass self to the args parameter . The way you way you do it you invoke the method in the main thread and end up with the infinite loop there : self.run_clients_in_seperate_threads != self.run_clients_in_seperate_threads()

Related

How do I update the GUI from another thread? using python

What is the best way to update a gui from another thread in python.
I have main function (GUI) in thread1 and from this i'm referring another thread (thread2), is it possible to update GUI while working in Thread2 without cancelling work at thread2, if it is yes how can I do that?
any suggested reading about thread handling. ?
Of course you can use Threading to run several processes simultaneously.
You have to create a class like this :
from threading import Thread
class Work(Thread):
def __init__(self):
Thread.__init__(self)
self.lock = threading.Lock()
def run(self): # This function launch the thread
(your code)
if you want run several thread at the same time :
def foo():
i = 0
list = []
while i < 10:
list.append(Work())
list[i].start() # Start call run() method of the class above.
i += 1
Be careful if you want to use the same variable in several threads. You must lock this variable so that they do not all reach this variable at the same time. Like this :
lock = threading.Lock()
lock.acquire()
try:
yourVariable += 1 # When you call lock.acquire() without arguments, block all variables until the lock is unlocked (lock.release()).
finally:
lock.release()
From the main thread, you can call join() on the queue to wait until all pending tasks have been completed.
This approach has the benefit that you are not creating and destroying threads, which is expensive. The worker threads will run continuously, but will be asleep when no tasks are in the queue, using zero CPU time.
I hope it will help you.

Python - Threads not parallel

I have my runner code that starts 5 threads, however, it only starts 1 thread (by which I know because it doesn't loop), take a look at the code:
import Handle
import threading
h = Handle.Handle()
h.StartConnection()
for i in range(0, 5):
print("Looped")
t = threading.Thread(target=h.Spawn())
t.start()
It only prints "Looped" once and only runs "Spawn" once aswell. Any ideas?
The issues I noticed:
You are replacing the t variable in each loop. So finally you just have one thread assigned to it.
Does the Spawn function return a function? If it does then it's okay, otherwise you should just pass Spawn to the target, not call Spawn() .
If the Spawn function is long running in nature (I assume it is), then your call to the Spawn function will block the loop and wait until it returns. This is why your loop might print "looped" once and the Spawn function getting called just once too.
My suggestion would be like this:
import Handle
import threading
h = Handle.Handle()
h.StartConnection()
threads = []
for i in range(0, 5):
print("Looped")
t = threading.Thread(target=h.Spawn)
threads.append(t)
t.start()
I took a list to store the threads - the threads list. Then appending each of the thread in it before calling start. Now I can iterate over the threads list anytime I want (may be for joining them?).
Also since I assumed Spawn is a long running function, I passed it as the target to the Thread constructor. So it should be run in background when we call start on the thread. Now it should no longer block the loop.
You are not running threads, you run the Spawn-method right in the main thread. target needs to be a function, not the result of that function:
t = threading.Thread(target=h.Spawn)
Try this code .
import Handle
import threading
h = Handle.Handle()
h.StartConnection()
for i in range(0, 5):
print("Looped")
threading.Timer(5.0, h).start()

new thread blocks main thread

from threading import Thread
class MyClass:
#...
def method2(self):
while True:
try:
hashes = self.target.bssid.replace(':','') + '.pixie'
text = open(hashes).read().splitlines()
except IOError:
time.sleep(5)
continue
# function goes on ...
def method1(self):
new_thread = Thread(target=self.method2())
new_thread.setDaemon(True)
new_thread.start() # Main thread will stop there, wait until method 2
print "Its continues!" # wont show =(
# function goes on ...
Is it possible to do like that?
After new_thread.start() Main thread waits until its done, why is that happening? i didn't provide new_thread.join() anywhere.
Daemon doesn't solve my problem because my problem is that Main thread stops right after new thread start, not because main thread execution is end.
As written, the call to the Thread constructor is invoking self.method2 instead of referring to it. Replace target=self.method2() with target=self.method2 and the threads will run in parallel.
Note that, depending on what your threads do, CPU computations might still be serialized due to the GIL.
IIRC, this is because the program doesn't exit until all non-daemon threads have finished execution. If you use a daemon thread instead, it should fix the issue. This answer gives more details on daemon threads:
Daemon Threads Explanation

Python Threading - Managing thread termination and the main thread

Before you read on, know that I'm new to Python and very new to threading so forgive me if I misunderstand how threads work or make a rookie error :P
Short description of my goal:
The main thread (a) does some things (e.g. prints "begin!")
Main thread spawns a new thread (b) that first prints "Thread B
started" and then prints x+1 forever (1, 2, 3 ...)
Main thread prints "Woop!"
Then the end of the main thread is reached, it terminates itself and
then switches to thread b making b the main thread
Program is now running thread b as the main thread so is just
printing x+1 forever and a has been forgotten and is no longer
relevant
Ctrl+C will terminate thread b and effectively, the whole program
will be terminated because thread a doesn't exist anymore
Here's what I have so far (the basics):
import threading, time
def printCount():
print "Thread B started"
x = 0
while True:
time.sleep(1)
x = x + 1
print x
## User Code ##
print "begin!"
threadB = threading.Thread(target=printCount)
threadB.start()
print "woop!"
The requirements are:
I don't want to modify below the 'User Code' mark much at all. I
certainly don't want to wrap it in a class, a function or it's own
thread
Pressing Ctrl+C at any point should terminate the entire program
with no threads left running (Using something like: except
KeyboardInterrupt: os._exit(1)) inside User Code is fine
Thread a may continue to run instead of making thread b the main
thread, but in this case, I don't want the code to handle Ctrl+C
terminating the entire program inside the User Code section
This example is not my actual goal, just a simplified version of the problem I'm having. I'm trying to make an IRC framework where the user can import it and use the API very simply without messying their own code with threads and interrupts and the like. This is why it's important for the user code to be as clean as possible.
The framework would allow the user to create an IRC bot which runs forever, listening to commands whilst allowing the user to add their own commands. The Github link is here if you're interested (It's very WIP atm).
You cannot "switch" threads. So once you're done with your main thread, you have to wait for the other threads to terminate using the method join. But note this:
Since the join method is not interruptible with KeyboardInterrupt, you need to specify a timeout and loop over to detect user interrupts.
Since you can't force a thread to terminate, you have to implement a stop mecanism using threading.Event for instance
You also need to use threading.Lock to prevent concurrent access on shared resources, like sys.stdout (used when you print)
I gathered these aspects in a class called ThreadHandler, please have a look:
import threading, time
def printCount(lock, stop):
with lock:
print "Thread B started"
x = 0
while not stop.is_set():
time.sleep(1)
x = x + 1
with lock:
print x
class ThreadHandler():
STEP = 0.2
def __init__(self, target):
self.lock = threading.Lock()
self.stop = threading.Event()
args = (self.lock, self.stop)
self.thread = threading.Thread(target=target, args=args)
def start(self):
self.thread.start()
def join(self):
while self.thread.is_alive():
try:
self.thread.join(self.STEP)
except KeyboardInterrupt:
self.stop.set()
## User Code ##
print "begin!"
handler = ThreadHandler(target=printCount)
handler.start()
with handler.lock:
print "woop!"
handler.join()
Wrote a short note on another question yesterday having similar issues, this is a check you could implement in the subthread "b":
Instead of while 1: do the following:
def printCount():
main = None
for t in threading.enumerate():
if t.name == 'MainThread':
main = t
print "Thread B started"
x = 0
while main and main.isAlive():
time.sleep(1)
x = x + 1
print x
It would be a good idea to store main in the global scope for all threads to use isntead of having to look up the main thread each and every initation of the sub-thread.
But this would do the work in your example.
main will be the handle towards your main thread by iterating through all threads (.enumerate()) and then placing the thread called "MainThread" into main and then calling main.isAlive() to check if it's still running.
if main is None or False or if .isAlive() returns False it will indicate that the thread is either non-existant or dead, shutting down your subthread :)
You can't switch threads like that. It doesn't work like that.
However you could use signals with a global flag ALIVE:
import threading, time, signal
ALIVE = True
def handle_sigint(signum, frame):
global ALIVE
ALIVE = False
signal.signal(signal.SIGINT, handle_sigint)
def printCount():
print "Thread B started"
x = 0
while ALIVE: # <--- note the change
time.sleep(1)
x = x + 1
print x
## User Code ##
print "begin!"
threadB = threading.Thread(target=printCount)
threadB.start()
print "woop!"
signal.pause() # <--- wait for signals
Now it will gracefully quit after pressing CTRL+C.

python threading blocks

I am trying to write a program which creates new threads in a loop, and doesn't wait for them to finish.
As I understand it if I use .start() on the thread, my main loop should just continue, and the other thread will go off and do its work at the same time
However once my new thread starts, the loop blocks until the thread completes.
Have I misunderstood how threading works in Python, or is there something stupid I'm doing?
Here is my code for creating new threads.
def MainLoop():
print 'started'
while 1:
if not workQ.empty():
newThread = threading.Thread(target=DoWorkItem(), args=())
newThread.daemon = True
newThread.start()
else:
print 'queue empty'
This calls the function and passes its result as target:
threading.Thread(target=DoWorkItem(), args=())
Lose the parentheses to pass the function object itself:
threading.Thread(target=DoWorkItem, args=())

Categories