python multithreading how member function of threads call functions outside class - python

I read the example code following. What I wonder this how member function of myThread, run can call function defined outside class, myThread.
Is it normal to code in this way when using multithreading?
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print "Starting " + self.name
print_time(self.name, 5, self.counter)
print "Exiting " + self.name
def print_time(threadName, counter, delay):
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
print "%s: %s" % (threadName, time.ctime(time.time()))
counter -= 1
# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
print "Exiting Main Thread"
https://www.tutorialspoint.com/python/python_multithreading.htm

This actually has nothing to do with multithreading. You can easily come up with an example of class methods calling functions outside of the class
def func():
# something
class A:
def method(self):
func()
In python, when you call a function, it will search for that name. Since you declared(defined) the function in global namespace(by def func()), it finds it and executes it. That's just some normal python behavior which has nothing to do with multithreading.
However, when it comes to whether it's normal to code this way, it depends. It's not a horrible thing to have a "global" function which you can call from anywhere in this file. Actually that's how C works. But if you want your code to be more "object-oriented", you should probably put this function in some class and use it from there. That's really a design issue, or maybe a coding style discussion.

after assigning the thread a function to execute, it will wait to be manually started, so thread1.start() means --> you can start now and you can do your job.
def run(self):
print "Starting " + self.name
print_time(self.name, 5, self.counter)
print "Exiting " + self.name
Code to execute when the thread is starting.

Related

python Thread.name is printing last thread created name

I'm a newbie to Python and learning about threads. I have created a sample Producer-Consumer code wherein I add a movie to a list in Producer thread and pop the front element from the same list in Consumer thread. The problem is while printing the items of the movie List along with thread name I'm getting incorrect thread name in Producer thread. This is my code
Producer.py
from threading import Thread
from threading import RLock
import time
class Producer(Thread):
def __init__(self):
Thread.__init__(self)
Thread.name = 'Producer'
self.movieList = list()
self.movieListLock = RLock()
def printMovieList(self):
self.movieListLock.acquire()
if len(self.movieList) > 0:
for movie in self.movieList:
print(Thread.name, movie)
print('\n')
self.movieListLock.release()
def pushMovieToList(self, movie):
self.movieListLock.acquire()
self.movieList.append(movie)
self.printMovieList()
self.movieListLock.release()
def run(self):
for i in range(6):
self.pushMovieToList('Avengers' + str(i + 1))
time.sleep(1)
Consumer.py
from threading import Thread
import time
class Consumer(Thread):
def __init__(self):
Thread.__init__(self)
Thread.name = 'Consumer'
self.objProducer = None
def popMovieFromList(self):
self.objProducer.movieListLock.acquire()
if len(self.objProducer.movieList) > 0:
movie = self.objProducer.movieList.pop(0)
print(Thread.name, ':', movie)
print('\n')
self.objProducer.movieListLock.release()
def run(self):
while True:
time.sleep(1)
self.popMovieFromList()
Main.py
from Producer import *
from Consumer import *
def main():
objProducer = Producer()
objConsumer = Consumer()
objConsumer.objProducer = objProducer
objProducer.start()
objConsumer.start()
objProducer.join()
objConsumer.join()
main()
I am not sure whether you solve this problem.
Hope my answer will be helpful.
You can check the document of threading.
Here it says that Thread.name may set same name for multiple thread.
name
A string used for identification purposes only. It has no semantics. Multiple threads may be given the same name. The initial name is set by the constructor.
I think Thread.name is a static variable so it shares in different thread.
If you want to set name of thread, you can set it in thread object like this:
class Producer(Thread):
def __init__(self):
Thread.__init__(self)
self.name= 'Producer'
and get it by threading.current_thread().name.
if len(self.movieList) > 0:
for movie in self.movieList:
print(threading.current_thread().name, movie)
Hope you enjoy it!

Modifying and acessing of variables of a different class by thread in python

Am very much new to python. So what i might be asking may not be correct. What am looking to do is. Create a thread from mainss and start the thread. When the thread is started i want it to access the variable of the mainss class from where thread is created and Modify the variable values. And i want the execution of mainss to sleep until thread modifies one of its variable value. How can i achieve this? Here is the code i tried below. Comment in the code of mythread.py class is where I need to modify the value of count variable of mainss class
main.py
#!/usr/bin/python
import time
from myThread import myThread
class mainss():
def __init__(self):
print "s"
def callThread(self):
global count
count = 1
# Create new threads
thread1 = myThread(1, "Thread-1", 1, count)
thread1.start()
# time.sleep(10) until count value is changed by thread to 3
print "Changed Count value%s " % count
print "Exiting"
m = mainss()
m.callThread()
myThread.py
#!/usr/bin/python
import threading
import time
exitFlag = 0
class myThread (threading.Thread):
def __init__(self, threadID, name, counter, count):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
self.count = count
def run(self):
print_time(self.name, 1, 5, self.count)
def print_time(threadName, delay, counter, count):
from main import mainss
while counter:
if exitFlag:
threadName.exit()
time.sleep(delay)
count = count + 1
print "count %s" % (count)
# here i want to modify count of mainss class
counter -= 1
Thanks in advance
Using Multiprocessing, a Manager dictionary is used to communicate between or to processes https://pymotw.com/3/multiprocessing/communication.html#managing-shared-state Note that the Manager dictionary can be changed while the process is running. Multiprocessing also has a wait feature https://pymotw.com/3/multiprocessing/communication.html#signaling-between-processes
I would use a threading.Event and a Queue
Something like this, (Please note that i didn't test this myself and obviously you gonna have to make some changes.)
main.py
import Queue
import threading
from myThread import myThread
class mainss:
def __init__(self):
self.queue = Queue.Queue()
self.event = threading.Event()
def callThread(self):
self.queue.put(1) # Put a value in the queue
t = myThread(self.queue, self.event)
t.start()
self.event.wait() # Wait for the value to update
count = self.queue.get()
print "Changed Count value %s" % count
if __name__ == '__main__':
m = mainss()
m.callThread()
myThread.py
import threading
class myThread(threading.Thread):
def __init__(self, queue, event):
super(myThread, self).__init__()
self.queue = queue
self.event = event
def run(self):
while True:
count = self.queue.get() # Get the value (1)
count += 1
print "count %s" % (count)
self.queue.put(count) # Put updated value
self.event.set() # Notify main thread
break

Python threading in multi subclasses

I have a series of classes that inherit from in a series and parallel manner and I need to use Python threading for all classes when possible. An example is below. The problem is that the Build class does not get its run function executed which is a method in the Thread class. Threading works fine in MyThread class though. Any idea how to make the Build class starts as a thread?
from threading import Thread
from random import randint
import time
class Build(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
# This run function currently not being executed
for i in range(20):
print('Second series %i in thread' % (i))
time.sleep(1)
class MyThread(Build, Thread):
def __init__(self, val):
''' Constructor. '''
Thread.__init__(self)
Build.__init__(self)
self.val = val
def run(self):
for i in range(1, self.val):
print('Value %d in thread %s' % (i, self.getName()))
# Sleep for random time between 1 ~ 3 second
secondsToSleep = randint(1, 5)
print('%s sleeping fo %d seconds...' % (self.getName(), secondsToSleep))
time.sleep(secondsToSleep)
# Run following code when the program starts
if __name__ == '__main__':
# Declare objects of MyThread class
myThreadOb1 = MyThread(4)
myThreadOb1.setName('Thread 1')
myThreadOb2 = MyThread(4)
myThreadOb2.setName('Thread 2')
# Start running the threads!
myThreadOb1.start()
myThreadOb2.start()
# Wait for the threads to finish...
myThreadOb1.join()
myThreadOb2.join()
print('Main Terminating...')`
FYI: Instead of subclassing threading.Thread the better way to achieve what you want is to make your class instances Callable and just pass them to the target keyword arg of the Thread class' constructor. The advantage of doing this is you can pass in additional arguments to each Thread instance.
going with your sample code.
class MyThread(Build):
def __init__(self):
''' Constructor. '''
Build.__init__(self)
self.val = val
# this allows your class to be a callable.
def __call__(self, val):
for i in range(1, val):
print('Value %d in thread %s' % (i, self.getName()))
# Sleep for random time between 1 ~ 3 second
secondsToSleep = randint(1, 5)
print('%s sleeping fo %d seconds...' % (self.getName(), secondsToSleep))
time.sleep(secondsToSleep)
# Run following code when the program starts
if __name__ == '__main__':
# Declare objects of MyThread class
myThreadObj1 = MyThread()
myThread1 = Thread(target=myThreadOb1, args=(4))
myThread1.start()

Python GUI stays frozen waiting for thread code to finish running

I have a python GUI program that needs to do a same task but with several threads. The problem is that I call the threads but they don't execute parallel but sequentially. First one executes, it ends and then second one, etc. I want them to start independently.
The main components are:
1. Menu (view)
2. ProcesStarter (controller)
3. Process (controller)
The Menu is where you click on the "Start" button which calls a function at ProcesStarter.
The ProcesStarter creates objects of Process and threads, and starts all threads in a for-loop.
Menu:
class VotingFrame(BaseFrame):
def create_widgets(self):
self.start_process = tk.Button(root, text="Start Process", command=lambda: self.start_process())
self.start_process.grid(row=3,column=0, sticky=tk.W)
def start_process(self):
procesor = XProcesStarter()
procesor_thread = Thread(target=procesor.start_process())
procesor_thread.start()
ProcesStarter:
class XProcesStarter:
def start_process(self):
print "starting new process..."
# thread count
thread_count = self.get_thread_count()
# initialize Process objects with data, and start threads
for i in range(thread_count):
vote_process = XProcess(self.get_proxy_list(), self.get_url())
t = Thread(target=vote_process.start_process())
t.start()
Process:
class XProcess():
def __init__(self, proxy_list, url, browser_show=False):
# init code
def start_process(self):
# code for process
When I press the GUI button for "Start Process" the gui is locked until both threads finish execution.
The idea is that threads should work in the background and work in parallel.
you call procesor.start_process() immediately when specifying it as the target of the Thread:
#use this
procesor_thread = Thread(target=procesor.start_process)
#not this
procesor_thread = Thread(target=procesor.start_process())
# this is called right away ^
If you call it right away it returns None which is a valid target for Thread (it just does nothing) which is why it happens sequentially, the threads are not doing anything.
One way to use a class as the target of a thread is to use the class as the target, and the arguments to the constructor as args.
from threading import Thread
from time import sleep
from random import randint
class XProcesStarter:
def __init__(self, thread_count):
print ("starting new process...")
self._i = 0
for i in range(thread_count):
t = Thread(
target=XProcess,
args=(self.get_proxy_list(), self.get_url())
)
t.start()
def get_proxy_list(self):
self._i += 1
return "Proxy list #%s" % self._i
def get_url(self):
self._i += 1
return "URL #%d" % self._i
class XProcess():
def __init__(self, proxy_list, url, browser_show=False):
r = 0.001 * randint( 1, 5000)
sleep(r)
print (proxy_list)
print (url)
def main():
t = Thread( target=XProcesStarter, args=(4, ) )
t.start()
if __name__ == '__main__':
main()
This code runs in python2 and python3.
The reason is that the target of a Thread object must be a callable (search for "callable" and "__call__" in python documentation for a complete explanation).
Edit The other way has been explained in other people's answers (see Tadhg McDonald-Jensen).
I think your issue is that in both places you're starting threads, you're actually calling the method you want to pass as the target to the thread. That runs its code in the main thread (and tries to start the new thread on the return value, if any, once its done).
Try:
procesor_thread = Thread(target=procesor.start_process) # no () after start_process
And:
t = Thread(target=vote_process.start_process) # no () here either

Why doesn’t this thread terminate?

I am trying to use the python threading module. As I am sysadmin, I struggle a little bit when developing; and this concept is kind of new for me. I launch two threads and I want to stop them, when the main thread sets a flag to False:
class My_Thread( threading.Thread):
def __init__(self, thread_id, thread_name, count):
threading.Thread.__init__(self)
self.thread_id = thread_id
self.thread_name = thread_name
self.count = count
def run(self):
do_job(self.thread_name, self.thread_id, self.count)
def do_job(t_name, t_id, count):
while not get_kill():
print "It is "+str(time.time())+" and I am "+str(t_name)
print get_kill()
time.sleep(count)
kill = False
def get_kill():
return kill
def set_kill(state):
kill = state
if __name__ == '__main__':
a = My_Thread(1, "Thread-1", 2)
b = My_Thread(2, "Thread-2", 1)
a.start()
b.start()
while(True):
try:
pass
except KeyboardInterrupt,ki:
set_kill(True)
sys.exit(0)
But the value is never read as changed in both threads and they don't exit. Why is this value not properly read from threads?
The problem
In set_kill(), you are creating a new local variable kill setting it to state, and returning from the function. You are not actually updating the value of kill in the global scope.
To do that, you would need to have:
def set_kill(state):
global kill
kill = state
A better way
Using globals like that is generally considered bad practice, you probably want to convert your kill variable and functions into an object, to encapsulate that data and behaviour together:
class Kill(object):
kill = False
def get(self):
return self.kill
def set(self, value):
self.kill = value
Which you would use like this:
class MyThread(Thread):
def __init__(self, thread_id, thread_name, count, kill):
self.kill = kill
...
def do_job(self, ...):
while not self.kill.get():
...
if __name__ == '__main__':
kill = Kill()
a = My_Thread(1, "Thread-1", 2, kill)
b = My_Thread(2, "Thread-2", 1, kill)
...
kill.set(True)

Categories