So I'm new to Python and I'm learning about multi threading. I watched a video on how to do it and followed. I got this:
from threading import *
from time import sleep
class Hello(Thread):
def run(self):
for i in range(5):
print("Hello")
sleep(1)
class Hi(Thread):
def run(self):
for i in range(5):
print("Hi")
sleep(1)
t1 = Hello()
t2 = Hi()
t1.start()
sleep(0.2)
t2.start()
Which prints Hello and Hi simultaneously. But I'm confused about the start used in t1.start() and t2.start() because the classes Hello and Hi don't have a start method. What if I have different methods with different names, how can I call them?
Thank you in advance!
Couple of points:
(1) A Hello instance is a Thread instance. You wrote, class Hello(Thread): .... That declares your Hello class to be a specialization of the Thread class. Your Hello object has a start() method because the Thread class has a start() method.
(2) A Thread instance is not a thread. A thread is an operating system object. A Thread instance is a "handle" that your program uses to create and interact with an operating system thread. The t1.start() call is where the new thread gets created.
(3) After a new thread is created by t1.start(), it will call t1.run(). That's carved in stone. You can't change it, BUT...
(4) ...You write the run() method yourself. It will do whatever you make it do. If you want the thread to call some self.foobar() method, then all you have to do is put a call to self.foobar() inside your run() method.
Related
I have a function in thread A which needs to wait until a function in thread B is called.
The function in thread B is called periodically, so it just needs to wait until the next time it is called. This allows me to sync up with it.
How would I do this?
(Sorry if this is trivial.)
It may be a principle of computer science that no multithreading question is trivial.
There are various ways to do this, but one of the simplest involves the use of a threading.Event object. Events are the simplest of the so-called synchronization primitives. See the manual section on the threading module for more ideas. Here is a working example:
#! python3.8
import threading
import time
t0 = time.time()
def elapsed_time():
return time.time() - t0
class StopMe:
def __init__(self):
self.running = True
def main():
ev1 = threading.Event()
stop = StopMe()
th1 = threading.Thread(target=thread1, args=(ev1, stop))
th1.start()
for _ in range(10):
ev1.wait()
print("The function was just called", elapsed_time())
ev1.clear()
stop.running = False
th1.join()
print("Exit", elapsed_time())
def thread1(event, stop):
def a_function():
event.set()
print("I am the function", elapsed_time())
while stop.running:
time.sleep(1.0)
a_function()
main()
Output:
I am the function 1.0116908550262451
The function was just called 1.0116908550262451
I am the function 2.0219264030456543
The function was just called 2.0219264030456543
I am the function 3.0322916507720947
The function was just called 3.0322916507720947
I am the function 4.033170938491821
The function was just called 4.033170938491821
I am the function 5.043376445770264
The function was just called 5.043376445770264
I am the function 6.043909788131714
The function was just called 6.043909788131714
I am the function 7.054021596908569
The function was just called 7.054021596908569
I am the function 8.06399941444397
The function was just called 8.06399941444397
I am the function 9.064924716949463
The function was just called 9.064924716949463
I am the function 10.066757678985596
The function was just called 10.066757678985596
I am the function 11.076870918273926
Exit 11.076870918273926
Some things to note here:
Once you put a synchronization primitive into your code, you need to give some thought about how to terminate the thread gracefully, and how to terminate the application as a whole. In this example, the threads communicate through the little "StopMe" object, and through the Event object. Note that the main thread may have to wait one second until the secondary thread finishes its sleep function. That occurs if thread1 begins its time delay before the main thread calls the join function. That didn't happen in my test run but it might, depending on how CPU time slices are given to the different threads. If that's not acceptable to you, you have to write more code to get around it.
Also note that the function call ev1.wait() will block the main thread until the event is set from the secondary thread. In a GUI application that is not what you want.
I ran this with Python3.8 but the program doesn't use any version-specific features, so it should work the same with any reasonably recent version of Python.
I have a class function in python.
I run the class in many different instances
class worker():
def__init__(x,x)
def run():
instance1 = worker(x,x)
instance1.run()
instance2 = worker(x,x)
instance2.run()
The problem is if first instance1 encounter thread.sleep() it affects the other instance2. How do i make them independent. Better if without multi-process Thank you!
Different example:
__author__ = 'user'
import time
class test():
def __init__(self, message):
self.message=message
def run(self):
while True:
print self.message
time.sleep(5)
if __name__ == '__main__':
test1 = test("PRINT-1")
test1.run()
test2 = test("PRINT-2")
test2.run()
you can use Celery for run parallel tasks. It's easy to implement.
See an example:
import time
from celery import task
#task
def make_task():
time.sleep(5)
return True
def execute_tasks():
result = group([make_task.s(), make_task.s()]).apply_async() # Execute tasks
print result.get() # Print the result
It looks like you're half-followed a tutorial on parallel code. Nothing in your current test class will cause it to run in parallel, but with just some minor tweaks you can do so with either threads or processes.
Here's a version that makes the class inherit from threading.Thread:
import threading
import time
class TestThreaded(threading.Thread):
def __init__(self, x, y):
super().__init__()
self.x = x
self.y = y
def run(self):
for i in range(self.x):
time.sleep(self.y)
print((i+1)*self.y)
You can use it like this:
t0 = TestThreaded(8, 3)
t1 = TestThreaded(6, 4)
t0.start()
t1.start()
t0.join()
t1.join()
Both threads in this example will count to 24 over a span of 24 seconds. The first thread will count by threes, the second thread will count by fours. The timings will be closely synched at 12 and 24 seconds (depending on your computer's exact timings they may get printed on the same line).
Note that we're calling the start method inherited from the Thread class, not the run method we defined above. The threading code will call run for us, in the spawned thread.
You can get an equivalent multiprocessing version by using multiprocessing.Process as the base class instead of threading.Thread. The only difference is that you'll spawn child processes instead of child threads. For CPU limited work in Python, processes are better than threads because they're not limited by the Global Interpreter Lock, which makes it impossible for two threads to run Python code at the same time. The downside is higher overhead, both during startup, and when communicating between processes.
well,I wrote a little snappet trying to know how to use python threading .
But strangely the following code just quit quickly without the expected output.
Is it because I shouldn't spawn threads by overiding the run() method?
import threading
from time import sleep
class mythread(threading.Thread):
def __init__(self,target=None,thread_num=5):
threading.Thread.__init__(self,target=None)
self.thn = thread_num
def run(self):
for i in range(self.thn):
t = threading.Thread(target=self.myfunc)
t.start()
t.join()
myfunc(self.thn)
def myfunc(num):
print num,'\tI am doing sth.'
sleep(0.5)
print num,'\tI have done it.'
mythread()
You need to start the thread to make it actually do something:
t = mythread()
t.start()
If you bother to accept a target parameter in your constructor (why?), you shouldn't ignore this parameter. Maybe you want to pass it on to the Thread constructor. (Why?)
When you write mythread(), you instantiate the object. THe default constructor will be called, so __init__() will be executed.
You constructor doesn't have the any instruction of starting the thread.
I've been mucking around with python for a little while and I have recently come up with something involving multithreading... without further ado... heres what I have...
import pythoncom
import wmi
import threading
class Info(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
pythoncom.CoInitialize()
c = wmi.WMI()
detect = c.Win32_ComputerShutdownEvent.watch_for()
detect()
return
if __name__ == '__main__':
Info().start()
for process in c.Win32_Process(Name="something.exe"):
result = process.Terminate()
So my question is... Why does this work? It may be an overall question regarding the process of the inheritence of threading.Thread... but there is no start() def in the class Info() so why does the run def begin?
This is actually a pretty handy application I needed to use to stop an application that always seems to hang when windows shuts down... finding when the windows shutdown event happens was a bit of a headache but luckily tim golden's masterpiece saves the day!
Because it's defined in the parent. Parent classes are checked for attributes if they're not found (or handled) in the child class.
Subclasses of Thread automatically call their run(), when you call start() on them. Start is defined in Thread.
From the docs
There are two ways to specify the activity: by passing a callable object to the constructor, or by overriding the run() method in a subclass.
and from docs on start()
It arranges for the object’s run() method to be invoked in a separate thread of control.
Don't you intent to wait the thread has ended before killing process ?
If so:
if __name__ == '__main__':
info = Info()
info.start()
info.join()
for process in c.Win32_Process(Name="something.exe"):
result = process.Terminate()
obj = functioning()
from threading import Thread
Thread(target=obj.runCron(cronDetails)).start()
print "new thread started..."
I am runnning this, this should run as new thread for runCron function and should print new thread started. but this is not printing new thread started and not creating new thread
You question is missing some details, e.g. what error message you are getting, etc. – below is a working example mimicked after your code.
#!/usr/bin/env python
import time
class Obj(object):
def runCron(self, cronDetails):
time.sleep(1)
print cronDetails
obj = Obj()
cronDetails = "I'm here."
from threading import Thread
# Note, that the `target` is a function object
# (or a callable in general), we don't actually call it yet!
t = Thread(target=obj.runCron, args=(cronDetails, ))
t.start()
print "New thread started (should be here in a second) ..."
It prints:
New thread started (should be here in a second) ...
I'm here.
Looks like you want to call obj.runCron(cronDetails) inside the thread. But what that code does is to call obj.runCron(cronDetails) first, and then pass the result of that to the Thread class.
If that's the case, the code below should fix it:
obj = functioning()
from threading import Thread
Thread(target=obj.runCron, args=(cronDetails,)).start()
print "new thread started..."
Note that I'm not calling obj.runCron myself anymore, but passing that method with the arguments separately to threading.Thread so it can be called inside the thread with the correct arguments.
If that doesn't do what you want, please provide more info as I asked in the comment.