Create Thread on Class Method - python

How can I call thread on a class method passing it 'self'? I have a class defined as follows and want to call class method in new thread with self as argument. I tried following but self is not passed as argument
cust_obj = Customer()
thread.start_new_thread(cust_obj.process, ())
class Customer():
def __init__(self):
pass
def process(self):
self.fetch_data()
self.serialize_data()
def fetch_data(self):
# Fetch data logic
pass
def serialize_data(self):
# Serialize fetched data
pass

I believe you should put the class definition before the instance creating. Then it will work.
class Customer():
...
cust_obj = Customer()
thread.start_new_thread(cust_obj.process, ())

Related

How to override a function in a dict

As part of a message parser I have something similar to what is below, I want to be able to override some of the base class message functions as needed, but the override only works if I add a pass through function. I have lots of these functions and would like to not have to use a pass through function for every message function the child might override.
I know I could provide the functions that the child wants to override as part of the init append operation from the child, but the real messages are a lot more complicated than this simple example and doing that would break the rules I have set for the child classes.
First question is why does it not just work without the pass though, dictionaries are mutable, so the override should be called from the dictionary.
Second question, is there a solution that does not entail the pass though function or appending the override functions to the dictionary from the child init?
class Base():
def set_enable_ind(self):
print("using the pass through hack")
self.set_enable(self)
def set_enable(self):
print("In base class set_enable")
# base msg config dict
msgConfig = {
'setEnable': (set_enable),
}
msgConfigInd = {
'setEnable': (set_enable_ind),
}
def __init__(self, msgConfig=None):
# add the child's messages to the default ones
if msgConfig:
self.msgConfig.update(msgConfig)
self.msgConfigInd.update(msgConfig)
#this one calls the function directly
def msg_recived(self,msg):
self.msgConfig[msg](self)
# this one calls the pass though function
def msg_recived_ind(self,msg):
self.msgConfigInd[msg](self)
class Child(Base):
# override from base class
def set_enable(self, data = None, header=None):
print("In child class set_enable")
# add my own
def disconnect(self, data = None, header=None):
print("In child class disconnect_connection")
# each entry gets a function to call
BtMsgs = {
'disconnect' : (disconnect),
}
def __init__(self):
# call base class __init__ function first, adding my messages
Base.__init__(self, Child.BtMsgs)
if __name__ == "__main__":
child = Child()
#these both work as expected
child.msg_recived('disconnect')
child.msg_recived_ind('disconnect')
#this will always call the Base class function
child.msg_recived('setEnable')
#this will call the child function
child.msg_recived_ind('setEnable')
#output is as follow:
#In child class disconnect_connection
#In child class disconnect_connection
#In base class set_enable
#using the pass through hack
#In child class set_enable
The reason your msg_recived function always calls the Base.set_enable method is because of scoping. When you do:
class Base:
def set_enable(self):
print("In base class set_enable")
msgConfig = {
'setEnable': set_enable, # I removed parens here
}
...
you are telling Python to reference the nearest-scoped set_enable function (the one right above the dictionary).
The reason your Child class never calls its set_enable method, is because you haven't updated the reference in its own msgConfig dictionary. Calling the self.msgConfig.update method is only adding the new key/val reference to the disconnect method of the Child class.
If you change the Child.BtMsgs attribute/dict to have new references, it will work:
class Child(Base):
...
BtMsgs = {
'disconnect': disconnect,
'setEnable': set_enable,
}
def __init__(self):
super().__init__(Child.BtMsgs) # This is Python3.X+ convention
...
Output:
In child class disconnect_connection
In child class disconnect_connection
In child class set_enable
In child class set_enable
This is because 'setEnable': set_enable is now scoped to the one defined inside the Child class.
Regarding my original comment on your question about using __getitem__, getattr, and setattr:
You don't have to subclass dict for these methods to be useful.
class MsgConfig:
def __init__(self, **kwargs):
for attr in kwargs:
setattr(self, attr, kwargs[attr])
def __getitem__(self, item):
return self.__dict__.get(item)
def update(self, d):
if isinstance(d, MsgConfig):
d = d.__dict__
for k,v in d.items():
setattr(self, k, v)
class Base:
def set_enable(self):
print("In base class set_enable")
def __init__(self, msgConfig=None):
self.msgConfig = MsgConfig(setEnable=self.set_enable)
if msgConfig:
self.msgConfig.update(msgConfig)
def msg_recived(self,msg):
self.msgConfig[msg](self)
class Child(Base):
def set_enable(self, data = None, header=None):
print("In child class set_enable")
def disconnect(self, data = None, header=None):
print("In child class disconnect_connection")
def __init__(self):
super().__init__(MsgConfig(disconnect=self.disconnect))
if __name__ == "__main__":
child = Child()
child.msg_recived('disconnect')
child.msg_recived('setEnable')
Output:
In child class disconnect_connection
In child class set_enable
You could try modifying or extending the above class to work for you to automatically pull in necessary message function pointers.

Tracking decorated methods of children classes in python

In python, how can I setup a parent class to track methods with a specific decorator for each child seperatly? A quick code snippet of what I am trying to do:
class Parent:
decorated_func_dict = {} #dictionary that stores name->func for decorated functions
def get_func_by_decorator_name(self, name):
#stuff
pass
class Child1(Parent):
#func_name("Bob")
def bob_func(self, *args):
pass
#func_name("Tom")
def func2(self, *args):
pass
class Child2(Parent):
#func_name("Bob")
def func_bob2(self, *args):
pass
foo = Child1()
bar = Child2()
foo.get_func_by_decorator_name("Bob")
#Returns foo.bob_func
bar.get_func_by_decorator_name("Bob")
#Returns bar.func_bob2
Using Python 3.9.
A decorator is not something that makes a function look pretty. It is a callable that ingests an object (not only functions), does some arbitrary operations, and returns a replacement object.
In this case, your decorator should be storing references to function objects in a dictionary somewhere. The problem is that you won't be able to reference the class in which the functions are defined until it is created, which happens well after the decorator is run. You can avoid this by storing the name of the class as well as the name of the function.
The final step here is to properly bind the function objects to methods on the right object. That is something that get_func_by_decorated_name can do for you.
In sum, you can write something like this:
decorated_func_dict = {}
def func_name(cls_name, func_name):
def decorator(func):
decorated_func_dict.setdefault(cls_name, {})[func_name] = func
return func
return decorator
class Parent:
def get_func_by_decorator_name(self, name):
return decorated_func_dict[type(self).__name__][name].__get__(self)
class Child1(Parent):
#func_name("Child1", "Bob")
def bob_func(self, *args):
pass
#func_name("Child1", "Tom")
def func2(self, *args):
pass
class Child2(Parent):
#func_name("Child2", "Bob")
def func_bob2(self, *args):
pass
And indeed you get:
>>> foo.get_func_by_decorator_name("Bob")
<bound method Child1.bob_func of <__main__.Child1 object at 0x000001D58181E070>>
>>> bar.get_func_by_decorator_name("Bob")
<bound method Child2.func_bob2 of <__main__.Child2 object at 0x000001D582041F10>>
Another way to do this is to give your functions a name attribute, which you can then aggregate into a mapping in __init_subclass__ in Parent. This allows you to make an interface a bit closer to what you originally intended:
def func_name(func_name):
def decorator(func):
func.special_name = func_name
return func
return decorator
class Parent:
def __init_subclass__(cls):
cls.decorated_func_dict = {}
for item in cls.__dict__.values():
if hasattr(item, 'special_name'):
cls.decorated_func_dict[item.special_name] = item
del item.special_name # optional
def get_func_by_decorator_name(self, name):
return self.decorated_func_dict[name].__get__(self)
class Child1(Parent):
#func_name("Bob")
def bob_func(self, *args):
pass
#func_name("Tom")
def func2(self, *args):
pass
class Child2(Parent):
#func_name("Bob")
def func_bob2(self, *args):
pass
The results are identical to the first example.
The easiest way would of course be to get access to the child's namespace before the class is created, e.g. with a metaclass.

Listing all instance of a class

I wrote a Python module, with several classes that inherit from a single class called MasterBlock.
I want to import this module in a script, create several instances of these classes, and then get a list of all the existing instances of all the childrens of this MasterBlock class. I found some solutions with vars()['Blocks.MasterBlock'].__subclasses__() but as the instances I have are child of child of MasterBlock, it doesn't work.
Here is some example code:
Module:
Class MasterBlock:
def main(self):
pass
Class RandomA(MasterBlock):
def __init__(self):
pass
# inherit the main function
Class AnotherRandom(MasterBlock):
def __init__(self):
pass
# inherit the main function
Script:
import module
a=module.RandomA()
b=module.AnotherRandom()
c=module.AnotherRandom()
# here I need to get list_of_instances=[a,b,c]
Th ultimate goal is to be able to do:
for instance in list_of_instances:
instance.main()
If you add a __new__() method as shown below to your base class which keeps track of all instances created in a class variable, you could make the process more-or-less automatic and not have to remember to call something in the __init__() of each subclass.
class MasterBlock(object):
instances = []
def __new__(cls, *args, **kwargs):
instance = super(MasterBlock, cls).__new__(cls, *args, **kwargs)
instance.instances.append(instance)
return instance
def main(self):
print('in main of', self.__class__.__name__) # for testing purposes
class RandomA(MasterBlock):
def __init__(self):
pass
# inherit the main function
class AnotherRandom(RandomA): # works for sub-subclasses, too
def __init__(self):
pass
# inherit the main function
a=RandomA()
b=AnotherRandom()
c=AnotherRandom()
for instance in MasterBlock.instances:
instance.main()
Output:
in main of RandomA
in main of AnotherRandom
in main of AnotherRandom
What about adding a class variable, that contains all the instances of MasterBlock? You can record them with:
Class MasterBlock(object):
all_instances = [] # All instances of MasterBlock
def __init__(self,…):
…
self.all_instances.append(self) # Not added if an exception is raised before
You get all the instances of MasterBlock with MasterBlock.all_instances (or instance.all_instances).
This works if all base classes call the __init__ of the master class (either implicitly through inheritance or explicitly through the usual super() call).
Here's a way of doing that using a class variable:
class MasterBlock(object):
instances = []
def __init__(self):
self.instances.append(self)
def main(self):
print "I am", self
class RandomA(MasterBlock):
def __init__(self):
super(RandomA, self).__init__()
# other init...
class AnotherRandom(MasterBlock):
def __init__(self):
super(AnotherRandom, self).__init__()
# other init...
a = RandomA()
b = AnotherRandom()
c = AnotherRandom()
# here I need to get list_of_instances=[a,b,c]
for instance in MasterBlock.instances:
instance.main()
(you can make it simpler if you don't need __init__ in the subclasses)
output:
I am <__main__.RandomA object at 0x7faa46683610>
I am <__main__.AnotherRandom object at 0x7faa46683650>
I am <__main__.AnotherRandom object at 0x7faa46683690>

calling function of one class from other class in python

Suppose I have following code
class ter:
def func1()
def func2()
class fg:
def gl1()
def gl2()
ifTrue)
ter.func1() # func1 from class ter
How can I call func1 of class ter from class fg? ter.func1() is not working.
Since ter is the name of the class, ter.func1() is the syntax for calling a #staticmethod or (#classmethod). Generally, you shouldn't use classes in Python just for organizing functions; instead you'd use a "free function" or module-level function.
If you actually have an instance of the class ter, then you call the function on that name:
# Call an "instance method" on Person object
class Person:
def __init__(self, name): # Constructor
self.name = name
def sayHello(self): # Class method (requires `self` parameter)
print 'Hello, {0}'.format(self.name)
def main():
p = Person('Joe') # Instantiate `Person` class (calls constructor)
p.sayHello() # Call an "instance method" on Person object
If you're sure you want to use static methods:
class Person:
def __init__(self, name): # Constructor
self.name = name
def sayHello(self): # Class method (requires `self` parameter)
print 'Hello, {0}'.format(self.name)
#staticmethod
def makePerson(name): # Static Method (note, no `self` parameter)
p = Person(name)
return p
#classmethod
def makePerson2(cls, name): # Class method. First parameter is class
p = cls(name) # Call constructor for that class
return p
def main():
p2 = Person.makePerson('Joe') # Call static "factory" method
p2.sayHello()
Finally, even though Python doesn't have braces/brackets, it is very picky about syntax. If you're not going to declare a body of a method, you must use the pass keyword:
def foo():
pass # This function does nothing
class ter:
def func1(self):
print 'I am func1'
def func2(self):
pass
class fg:
def gl1(self):
pass
def gl2(self):
ter_object=ter()
ter_object.func1()
This should print I am func1.
The point to remember here is that you must create instances of classes unless you call static methods

Call another classes method in Python

I'm tying to create a class that holds a reference to another classes method. I want to be able to call the method. It is basically a way to do callbacks.
My code works until I try to access a class var. When I run the code below, I get the error What am I doing wrong?
Brian
import logging
class yRunMethod(object):
"""
container that allows method to be called when method run is called
"""
def __init__(self, method, *args):
"""
init
"""
self.logger = logging.getLogger('yRunMethod')
self.logger.debug('method <%s> and args <%s>'%(method, args))
self.method = method
self.args = args
def run(self):
"""
runs the method
"""
self.logger.debug('running with <%s> and <%s>'%(self.method,self.args))
#if have args sent to function
if self.args:
self.method.im_func(self.method, *self.args)
else:
self.method.im_func(self.method)
if __name__ == "__main__":
import sys
#create test class
class testClass(object):
"""
test class
"""
def __init__(self):
"""
init
"""
self.var = 'some var'
def doSomthing(self):
"""
"""
print 'do somthing called'
print 'self.var <%s>'%self.var
#test yRunMethod
met1 = testClass().doSomthing
run1 = yRunMethod(met1)
run1.run()
I think you're making this WAY too hard on yourself (which is easy to do ;-). Methods of classes and instances are first-class objects in Python. You can pass them around and call them like anything else. Digging into a method's instance variables is something that should almost never be done. A simple example to accomplish your goal is:
class Wrapper (object):
def __init__(self, meth, *args):
self.meth = meth
self.args = args
def runit(self):
self.meth(*self.args)
class Test (object):
def __init__(self, var):
self.var = var
def sayHello(self):
print "Hello! My name is: %s" % self.var
t = Test('FooBar')
w = Wrapper( t.sayHello )
w.runit()
Why not use this:
self.method(*self.args)
instead of this:
if self.args:
self.method.im_func(self.method, *self.args)
else:
self.method.im_func(self.method)
In your code you were calling self.method.im_func(self.method) - you shouldn't have been passing the method as argument but the object from which that method came. I.e. should have been self.method.im_func(self.method.im_self, *self.args)

Categories