Python threading in multi subclasses - python

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

Related

python multithreading how member function of threads call functions outside class

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.

Python - Starting two threads - Thread (t2) name error

This simple example seems to work fine but when I implement this same code in a only slightly more complicated codebase I get a error NameError: name 't2' is not defined when add is called from class QuoteReport using t2.add(key[0], key[1]). Is the way I am starting the two threads in main okay? Though this code seems to work is there anything here that is not good form? The only differnce I see from my simplified example and the one that fails is QueueReport and CallReport are in a seperate file from the main file. But I know the import is working because 1)if I change the code to t2 = CallReport_badname() it fails calls is cant find that class 2)I run some logging from the run method of CallReport and it does print to log. I would assume once those classes are imported I would call it as t2? is there anthing speical I should be doing when the instance of one class calls an instance of another class?
from threading import *
import time
class QueueReport(Thread):
def __init__(self):
Thread.__init__(self)
self.reports_to_call = {}
def add(self, user, report):
self.reports_to_call.update({(user, report): None})
print("Added Value - Queue Report")
print(len(self.reports_to_call))
def run(self):
print("Running - que\n")
time.sleep(10)
while True:
for key in self.reports_to_call:
print(key)
print("about to add to t2")
t2.add(key[0], key[1])
time.sleep(120)
class CallReport(Thread):
def __init__(self):
Thread.__init__(self)
self.reports_called = {}
def add(self, user, report):
self.reports_called.update({(user, report): None})
print("Added Value to reports called")
print("len2", len(self.reports_called))
def run(self):
print("Running - Call\n")
time.sleep(10)
while True:
for key in self.reports_called:
print("key from running", key)
#do something with this key and delete if succcessful
print("Call Report done- waiting to loop")
time.sleep(20)
if __name__ == '__main__':
t1 = QueueReport()
thread = Thread(target=t1.run)
thread.start()
t2 = CallReport()
thread2 = Thread(target=t2.run)
thread2.start()
t1.add("bob", "report2r")
time.sleep(1)
t1.add("tom", "report2")
time.sleep(1)
t1.add("harry", "report3")
time.sleep(15) # add new after first loop
t1.add("john", "report4")
Yes, there will be a difference if you move the logic into different files. t1 and t2 are declared in main method which makes them global variables and thus can be accessible by both the classes. If they are in different files you have to pass them around to access.
from threading import *
import time
class QueueReport(Thread):
def __init__(self, call_report_thread):
Thread.__init__(self)
self.reports_to_call = {}
self.call_report_thread = call_report_thread
def run(self):
print("Running - que\n")
time.sleep(10)
while True:
for key in self.reports_to_call:
print(key)
print("about to add to t2")
self.call_report_thread.add(key[0], key[1])
time.sleep(120)
class CallReport(Thread):
def __init__(self):
Thread.__init__(self)
self.reports_called = {}
def add(self, user, report):
self.reports_called.update({(user, report): None})
print("Added Value to reports called")
print("len2", len(self.reports_called))
def run(self):
print("Running - Call\n")
time.sleep(10)
while True:
for key in self.reports_called:
print("key from running", key)
#do something with this key and delete if succcessful
print("Call Report done- waiting to loop")
time.sleep(20)
if __name__ == '__main__':
t2 = CallReport()
t2.start()
t1 = QueueReport(t2)
t1.start()
I am assuming here that which thread starts first won't matter.

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

Printing an update line whenever a subprocess finishes in Python 3's multiprocessing Pool

I'm using Python's multiprocessing library to process a list of inputs with the built-in map() method. Here's the relevant code segment:
subp_pool = Pool(self.subprocesses)
cases = subp_pool.map(self.get_case, input_list)
return cases
The function to be run in parallel is self.get_case(), and the list of inputs is input_list.
I wish to print a progress prompt to the standard output in the following format:
Working (25/100 cases processed)
How can I update a local variable inside the class that contains the Pool, so that whenever a subprocess finishes, the variable is incremented by 1 (and then printed to the standard output)?
There's no way to do this using multiprocessing.map, because it doesn't alert the main process about anything until it's completed all its tasks. However, you can get similar behavior by using apply_async in tandem with the callback keyword argument:
from multiprocessing.dummy import Pool
from functools import partial
import time
class Test(object):
def __init__(self):
self.count = 0
self.threads = 4
def get_case(self, x):
time.sleep(x)
def callback(self, total, x):
self.count += 1
print("Working ({}/{}) cases processed.".format(self.count, total))
def do_async(self):
thread_pool = Pool(self.threads)
input_list = range(5)
callback = partial(self.callback, len(input_list))
tasks = [thread_pool.apply_async(self.get_case, (x,),
callback=callback) for x in input_list]
return [task.get() for task in tasks]
if __name__ == "__main__":
t = Test()
t.do_async()
Call the print_data() from the get_case() method and you are done.
from threading import Lock
Class A(object):
def __init__(self):
self.mutex = Lock()
self.count = 0
def print_data(self):
self.mutex.acquire()
try:
self.count += 1
print('Working (' + str(self.count) + 'cases processed)')
finally:
self.mutex.release()

override multiprocessing in python

how can i get variable in class which is override multiprocessing in python:
#!/usr/bin/env python
import multiprocessing
import os
class TestMultiprocess(multiprocessing.Process):
def __init__(self):
multiprocessing.Process.__init__(self)
self.myvar = ''
def myfunc(self):
return os.getpid()
def run(self):
self.myvar = self.myfunc()
mlist = []
for i in range(10):
t = TestMultiprocess()
mlist.append(t)
t.start()
for j in mlist:
t.join()
print t.myvar
i can not get value "myvar" from class TestMultiprocess, i just get blank. But i already override the run() function from Process.
sorry if my spell very bad ...
The run() will executed in a separate process; processes don't share memory, normally. multiprocessing does support shared variables, though, through the explicit Value class:
#!/usr/bin/env python
import multiprocessing
import os
class TestMultiprocess(multiprocessing.Process):
def __init__(self):
multiprocessing.Process.__init__(self)
self.myvar = multiprocessing.Value('i',0)
def myfunc(self):
return os.getpid()
def run(self):
self.myvar.value = self.myfunc()
mlist = []
for i in range(10):
t = TestMultiprocess()
mlist.append(t)
t.start()
for j in mlist:
j.join()
print j.myvar.value
replace t with j in the last loop
for j in mlist:
j.join() # t with j
print j.myvar # t with j
EDIT: and this will not solve your problem
by the way if you want to get the process pid you don't have to override the run() method just for that you can just do:
for j in mlist:
j.pid

Categories