Why doesn't this work ?
class spin(threading.Thread):
def __init__(self):
super(spin,self).__init__()
self._stop = False
def run (self,var):
self.var=var
print self.var
def echo (self,var):
self.var=var
print self.var
if __name__ == '__main__':
s = spin()
s.start('hello')
but this does?
s = spin()
s.echo('hello')
Im guessing its because the start sequence needs to be defined in the init ? but not sure how. someone asked for error codes from this:
s.start('hello')
TypeError: start() takes exactly 1 argument (2 given)
The reason s.start('hello') does not work is that the inherited Threadin.start() method takes no arguments other than self.
Calling s.echo('hello') does appear to work, but it calls the function in the context of the main thread instead of spawning a new thread.
One way to fix your code is by supplying var to the constructor:
import threading
class Spin(threading.Thread):
def __init__(self,var):
super(Spin,self).__init__()
self.var = var
def run(self):
print self.var
if __name__ == '__main__':
s = Spin('hello')
s.start()
s.join()
Related
I would like to build a function, which checks if a subthread is already running and if not, start a subthread with any function and paramter given. As multithreading tool I use this post: Is there any way to kill a Thread in Python?
The idea so far is the following:
from ThreadEx import ThreadEx
class MyClass:
def __init__(self):
self.__Thread = ThreadEx(name='MyClass',target="")
self.GlobalVariable = "MyClass Variable"
def SubThread(self, function):
if not self.__Thread.is_alive():
print("Thread is not alive")
self.__Thread = ThreadEx(target=function(),args=(self,))
print("Thread is going to start")
self.__Thread.start()
print("Thread started")
else:
print("There is already a subthread running")
def MyFunction1(self, argument1, argument2, argument3):
self.SubThread(lambda: MyFunction1(self, argument1,argument2,argument3))
def MyFunction2(self, argument1, argument2):
self.SubThread(lambda: MyFunction2,argument1,argument2)
def MyFunction1(self, argument1, argument2, argument3):
print(self.GlobalVariable)
print("MyFunction1")
print("Argument1: " + str(argument1))
print("Argument2: " + str(argument2))
print("Argument3: " + str(argument3))
def MyFunction2(argument1, argument2):
print("MyFunction2")
print("Argument1: " + str(argument1))
print("Argument2: " + str(argument2))
unfortunately if I execute:
from Myclass import MyClass
self.MyClass = MyClass()
self.MyClass.MyFunction1("Test1","Test2","Test3")
The output is:
Thread is not alive
MyClass Variable
MyFunction1
Argument1: Test1
Argument2: Test2
Argument3: Test3
Thread is going to start
Thread started
So the function is executed before the thread starts. So my question is, how do I send MyFunction including all arguments to a subthread and being able to repeat this with any other function without write a routine each time.
I was already looking for *args and **kwargs but I couldn't find the right syntax or it was the wrong way.
Thanks in advance! :)
Your problem is this line:
self.__Thread = ThreadEx(target=function(),args=(self,))
Notice the parentheses behind function. It means not the function is assigned to target, but the result of calling said function. So, the function is executed, it does its printing etc., then its output (None) is assigned to target, and then the thread starts.
Do this instead:
self.__Thread = ThreadEx(target=function,args=(self,))
The more generic alternative to those lambdas is to use *args and **kwargs, as you mention. It should look like this:
class MyClass:
# ... other class code goes here
def SubThread(self, function, *args, **kwargs): # changed
if not self.__Thread.is_alive():
print("Thread is not alive")
self.__Thread = ThreadEx(target=function,args=args, kwargs=kwargs) # changed
print("Thread is going to start")
self.__Thread.start()
print("Thread started")
else:
print("There is already a subthread running")
def MyFunction1(self, argument1, argument2, argument3):
self.SubThread(MyFunction1, self, argument1, argument2, argument3) # changed, note explicit inclusion of self
# ... function code goes here
my_instance = MyClass()
my_instance.MyFunction1("Test1","Test2","Test3")
my_instance.SubThread(MyFunction1, my_instance, "Test1", "Test2", "Test3") # note explicit inclusion of my_instance
I'm trying to run a function function of a class Foo in multiple subprocesses created by multiprocessing.pool in my main fileMain.py.
import sys
import multiprocessing
from Foo import Foo
f = Foo()
def get(n):
print f.ID
sys.stdout.flush() # Print the used instance's ID immediately
return f.function(n)
def calculate():
s = pool.map_async(get,range(4))
return s.get()
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
result = calculate()
pool.close()
The class Foois defined in Foo.py like
import random
class Foo():
def __init__(self):
print 'Initialized!'
self.ID = random.random() # Assign an unique ID to spot instance
pass
def function(self,x):
return x**2
The output I get is (with the ID obviously randomly)
Initialized!
Initialized!
0.955181146828
0.955181146828
0.955181146828
0.955181146828
>>> Initialized!
Initialized!
Initialized!
I want to avoid that a new instance of Foo is created by every subprocess. Why is this happening although all subprocesses then use the same instance as desired?
Notice also that f = Foo() cannot be placed after if __name__ == '__main__': or else
NameError: global name 'f' is not defined
I have a little doubt if one could solve my issue, and create successful communication between threads.
First example and this is how it should be working, but does not work well:
import Queue,threading,time
class th(threading.Thread):
def __init__(self,q):
threading.Thread.__init__(self)
self.q = q
self.t = time
def run(self):
for i in range(5):
self.q.put(i)
self.t.sleep(0.5) # <----------
self.q.put('end')
class main(object):
def __init__(self):
self.q = Queue.Queue()
self.thread = th(self.q)
self.thread.setDaemon(True)
self.thread.run()
self.call()
def call(self):
while True:
recv = self.q.get();
if recv == 'end':
break
else:
print recv
if __name__ == '__main__':
root = main()
root.call()
In this example, all printed at the same time:
0,1,2,3,4
Second example:
import Queue,threading,time
class th(threading.Thread):
def __init__(self,q):
threading.Thread.__init__(self);
self.q = q
self.t = time
def run(self):
for i in range(5):
self.q.put(i) # <------ no sleep()
self.q.put('end')
class main(object):
def __init__(self):
self.q = Queue.Queue()
self.thread = th(self.q)
self.thread.setDaemon(True)
self.thread.run()
self.call()
def call(self):
while True:
recv = self.q.get()
if recv == 'end':
break
else:
print recv
if __name__ == '__main__':
root = main()
root.call()
the code is printed as it has to
0,
1
2
3
4
one to one
is there any way that the sleep function in the same way?
You don't want to call the run method on a thread directly. Call start instead, which will kick off the child thread, which will in turn run the run method.
Your current code is essentially single threaded, since the run call does the work of the child thread in the parent instead. The child thread is never actually started! (You're also calling your main.call method twice, which I'd expect to block or raise an exception, but that's a separate issue.)
sorry, it was something very simple, really simple, just had to replace
self.thread.run()
by
self.threat.start()
I want two objects of the same class to operate concurrently. The class "MyClass" has a function that connects an instance to another instance of the class. I also need to keep track of the objects that have been created (oList). what I am trying is:
main.py:
from MyClass import MyClass
import time
oList = []
class oCreator1(Thread):
def __init__(self):
Thread.__init__(self)
self.o1 = MyClass()
def run(self):
while 1:
time.sleep(1)
print "Hi"
def getO1(self):
return self.o1
class oCreator2(Thread):
def __init__(self):
Thread.__init__(self)
self.o2 = MyClass()
def run(self):
while 1:
time.sleep(1)
print "Bye!"
def getO2(self):
return self.o2
main():
threadList = []
global oList
oc1 = oCreator1()
threadList.append(oc1)
o1 = oc1.getO1()
oList.append(o1)
oc2 = oCreator2()
threadList.append(oc2)
o2 = oc2.getO2()
oList.append(o2)
o1.connToAnotherO(o2)
print oList
for t in threadList:
t.start()
t.join()
if __name__ == '__main__':
main()
But the only thing that is printed is "Hi". I really want to know the things I'm doing wrong and the right way to do it. Thank you in advance.
for t in threadList:
t.start()
t.join()
The t.join() call waits for the thread t to finish. That means when you start the first thread, you wait for it to finish before starting the second, but the first thread is just going to keep printing Hi forever. It'll never finish.
Don't join, or don't start joining until all threads have started.
Consider the situation: i have the class(third-party library) with method that used infinity loop:
class Worker(object):
...
def transator(self):
...
#if connected print data
while self.connected:
...
print data
if __name__ == "__main__":
worker = Worker()
worker.translator()
I use this class in my program and can not be changed. ( I looked code on github :) ).
What the best method to stop this method manually ? I need change self.connected to False outside this method. I have an idea, but I think it's very complicated.
import time
from threading import Thread
class Terminator(Worker):
...
def terminate(self):
time.sleep(10)
self.connected = False
if __name__ == "__main__":
ter = Terminator()
t = Tread(target=ter.terminate)
t.start()
ter.translator()
Are there other ways?
Q: "How to stop an infinite loop on the outside"
A: Read the documentation for the method/class which is using the infinite loop and look to see if there are any parameters which influence how it runs.
For your use case, it looks to me like you should just be able to pass the timeout parameter to the TwythonStreamer constructor...
Alternatively to mcgilson correct answer you could add a property-descriptor like:
def toggle_connect(self, singleton=[True]):
singleton[0] = not singleton[0]
return singleton
and after:
worker=Worker()
Worker.connected = property(toggle_connect)
You should be able to do something like the following:
import time
from threading import Thread
if __name__ == "__main__":
w = Worker()
t = Thread(target=w.transator)
t.start()
time.sleep(10)
w.connected = False
t.join()