Call Function inside of another class that is threaded - multithreading

I am writing a gui application in python. In one instance of the GUI I want to call a method inside of my thread class, but I don't want to call the initial run() method.
Here is an example of my Threaded class:
class SomeThread(Thread):
def __init__(self,queue):
self.queue = queue
Thread.__init__(self)
def SomeMethod():
print "success"
def run(self):
apple = "eat a apple"
self.queue.put(apple) # pass var into queue
I attempt to call the SomeMethod here
class SomeGUIClass(wx.Frame):
def MethodA(self,event):
SomeThread.SomeMethod()
But I get an error that states "type object 'SomeThread' has no attribute 'SomeMethod'. How can I call this SomeMethod function directly without executing the run(self) method?

I believe the text editor had some trouble with the tabs/spacing of certain elements. I got it to work after fixing the indentation by calling:
self.queue = Queue.Queue()
SomeThread(self.queue).SomeMethod()

Related

Dart: Store heavy object in an isolate and access its method from main isolate without reinstatiating it

is it possible in Dart to instantiate a class in an isolate, and then send message to this isolate to receive a return value from its methods (instead of spawning a new isolate and re instantiate the same class every time)? I have a class with a long initialization, and heavy methods. I want to initialize it once and then access its methods without compromising the performance of the main isolate.
Edit: I mistakenly answered this question thinking python rather than dart. snakes on the brain / snakes on a plane
I am not familiar with dart programming, but it would seem the concurrency model has a lot of similarities (isolated memory, message passing, etc..). I was able to find an example of 2 way message passing with a dart isolate. There's a little difference in how it gets set-up, and the streams are a bit simpler than python Queue's, but in general the idea is the same.
Basically:
Create a port to receive data from the isolate
Create the isolate passing it the port it will send data back on
Within the isolate, create the port it will listen on, and send the other end of it back to main (so main can send messages)
Determine and implement a simple messaging protocol for remote method call on an object contained within the isolate.
This is basically duplicating what a multiprocessing.Manager class does, however it can be helpful to have a simplified example of how it can work:
from multiprocessing import Process, Lock, Queue
from time import sleep
class HeavyObject:
def __init__(self, x):
self._x = x
sleep(5) #heavy init
def heavy_method(self, y):
sleep(.2) #medium weight method
return self._x + y
def HO_server(in_q, out_q):
ho = HeavyObject(5)
#msg format for remote method call: ("method_name", (arg1, arg2, ...), {"kwarg1": 1, "kwarg2": 2, ...})
#pass None to exit worker cleanly
for msg in iter(in_q.get, None): #get a remote call message from the queue
out_q.put(getattr(ho, msg[0])(*msg[1], **msg[2])) #call the method with the args, and put the result back on the queue
class RMC_helper: #remote method caller for convienience
def __init__(self, in_queue, out_queue, lock):
self.in_q = in_queue
self.out_q = out_queue
self.l = lock
self.method = None
def __call__(self, *args, **kwargs):
if self.method is None:
raise Exception("no method to call")
with self.l: #isolate access to queue so results don't pile up and get popped off in possibly wrong order
print("put to queue: ", (self.method, args, kwargs))
self.in_q.put((self.method, args, kwargs))
return self.out_q.get()
def __getattr__(self, name):
if not name.startswith("__"):
self.method = name
return self
else:
super().__getattr__(name)
def child_worker(remote):
print("child", remote.heavy_method(5)) #prints 10
sleep(3) #child works on something else
print("child", remote.heavy_method(2)) #prints 7
if __name__ == "__main__":
in_queue = Queue()
out_queue = Queue()
lock = Lock() #lock is used as to not confuse which reply goes to which request
remote = RMC_helper(in_queue, out_queue, lock)
Server = Process(target=HO_server, args=(in_queue, out_queue))
Server.start()
Worker = Process(target=child_worker, args=(remote, ))
Worker.start()
print("main", remote.heavy_method(3)) #this will *probably* start first due to startup time of child
Worker.join()
with lock:
in_queue.put(None)
Server.join()
print("done")

Python - can call same class twice(or more) in thread?

I don't very understand the classes logic in python but cannot answer on web.
I have create a class to generate person info:
class person:
def fristnameGen(gender):
...
def emailGen(firstname,surname):
...
i create a bot to call it like this:
from person import *
class bots:
def __init__(self):
self.person = person()
def createDB(self):
print(self.person.name)
#do something...
finally i call it by a button with thread
from bots import *
import threading
class Panel:
def __init__(self):
self.top = tk.Tk()
self.bot = bots()
self.buildUI()
def foo(self):
self.bot.createDB(self.stringPhone.get())
def threadTheAction(func, *args):
t = threading.Thread(target=func, args=args)
t.setDaemon(True)
t.start()
def buildUI(self):
Button = tk.Button(self.top, text ="Start", command = lambda :self.threadTheAction(self.foo))
I get this error:
TypeError: 'Panel' object is not callable
However, i call it directly, its work
Button = tk.Button(self.top, text ="Start", command = lambda :self.foo())
How to fix the error?
...
2. Moreover, i tried create p1 = person() and p2= person() and print it. Found p1 and p2 is a same person, i prefer each new a class have a new one. How to generate "new person" using classes?
Thank you
You seem to have a lot of confusion about Object Oriented Programming in Python. Some of your methods have self parameters and some do not, seemingly at random. That's the source of your current error.
The threadTheAction method in your Panel class is getting the Panel instance passed in as its first argument, but that's named func in the method (since you omitted self). The real function you're passing as an argument gets caught in the variable argument *args. When the thread tries unsuccessfully to call it, you get an exception. Adding self before func would fix the immediate problem:
def threadTheAction(self, func, *args):
I suspect if your code got further along, you'd run into other errors with other methods without self in their parameter lists. For instance, none of the methods you've shown in person are likely to work correctly.
As for your second question, you haven't shown enough of person to know what's happening, but you're probably doing instance variables wrong somehow. With no self parameter in the methods, that's almost inevitable (since you assign to self.whatever to set a whatever attribute on the current instance). If you need help squaring that away, I suggest you ask a separate question (Stack Overflow is best when each question is self-contained) and provide the full code for your person class.

How do I bind to a function inside a class and still use the event variable?

class Player():
def __init__():
...
def moveHandle(self, event):
self.anything = ...
box.bind("<Key>", Player.moveHandle)
The bind function sets self as the event variable and ignores/throws up an error for event. I can't find a way to pass the event argument to the correct variable and maintain self for that function, even if I use args*. I can do one or the other, but not both.
I'm probably just lacking some basic knowledge about classes to be honest, I taught them to myself and didn't do it very thoroughly.
If I made a syntax mistake, it's because of me rewriting out the code incorrectly; in my program, the code works until the variables get passed.
the problem is that you are trying to use an instance method as a class method.
consider the following:
class Player():
def __init__():
...
def moveHandle(self, event):
self.anything = ...
box.bind("<Key>", Player.moveHandle)
where box is an instance of something, but Player is not.
instead this:
class Player():
def __init__(self):
...
def moveHandle(self, event):
self.anything = ...
p = Player()
box.bind("<Key>", p.moveHandle)
creates an instance of the player class, and then binds to the instances method, not the class method.

Python - Implementing stop method in threading.Thread

I'm using threads in my project I want to subclass threading.Thread and implement the stop method there, so I can subclass this class. look at this -
class MyThread(threading.Thread):
__metaclass__ = ABCMeta
def run(self):
try:
self.code()
except MyThread.__StopThreadException:
print "thread stopped."
#abstractmethod
def code(self):
pass
def stop(self):
tid = self.get_id()
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid,
ctypes.py_object(MyThread.__StopThreadException))
ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, 0)
class __StopThreadException(Exception):
"""The exception I raise to stop the sniffing"""
pass
def get_id(self):
for tid, tobj in threading._active.items():
if tobj is self:
return tid
class SniffThread(MyThread):
def code(self):
sniff(prn=self.prn)
def prn(self, pkt):
print "got packet"
t = SniffThread()
t.start()
time.sleep(10)
t.stop()
It doesn't work because the StopThreadException is raised in the main thread, and I need to find a way to raise it in the SniffThread. Do you have better way to implement the stop method? I need to do it because I work with blocking functions and I need a way to stop the Thread. I know I can use the lfilter of the sniff function and keep a flag but I don't want to do this. I don't want to do it because it will only work with scapy and I want to make an abstract class that can be inherited with a stop method that will work for any thread, the solution needs to be in the MyThread class.
Edit: I looked here and changed my code.

How do I call outside function from class in python

How do i call an outside function from this class ?
def test(t):
return t
class class_test():
def test_def(q):
test_msg = test('Hi')
print (test_msg)
To call the class method, you can create an instance of the class and then call an attribute of that instance (the test_def method).
def test(t):
return t
class ClassTest(object):
def test_def(self):
msg = test('Hi')
print(msg)
# Creates new instance.
my_new_instance = ClassTest()
# Calls its attribute.
my_new_instance.test_def()
Alternatively you can call it this way:
ClassTest().test_def()
Sidenote: I made a few changes to your code. self should be used as first argument of class methods when you define them. object should be used in a similar manner.

Resources