Callback not called if it is a class method - python

Python newbie question: the callback method handlePackets never gets called if it is a class method. If it is not in a class it works fine. What can I do?
class Receiver:
def __enter__(self):
self.serial_port = serial.Serial('/dev/ttyUSB0', 115200)
self.xbee = ZigBee(self.serial_port, escaped=True, callback=self.handlePackets)
Logger.info('Receiver: enter')
return self
def __exit__(self ,type, value, traceback):
Logger.info('Receiver: exit')
self.serial_port.close()
def handlePackets(data):
Logger.info('Receiver: packet incoming')

I can bet it is because, whatever is calling your callback from within ZigBee is failing silently. The interpreter calls your function with 2 parameters, but as you have defined it -- it takes only one.
def handlePackets(self, data):
#^^^^

Related

modify a function of a class from another class

In pymodbus library in server.sync, SocketServer.BaseRequestHandler is used, and defines as follow:
class ModbusBaseRequestHandler(socketserver.BaseRequestHandler):
""" Implements the modbus server protocol
This uses the socketserver.BaseRequestHandler to implement
the client handler.
"""
running = False
framer = None
def setup(self):
""" Callback for when a client connects
"""
_logger.debug("Client Connected [%s:%s]" % self.client_address)
self.running = True
self.framer = self.server.framer(self.server.decoder, client=None)
self.server.threads.append(self)
def finish(self):
""" Callback for when a client disconnects
"""
_logger.debug("Client Disconnected [%s:%s]" % self.client_address)
self.server.threads.remove(self)
def execute(self, request):
""" The callback to call with the resulting message
:param request: The decoded request message
"""
try:
context = self.server.context[request.unit_id]
response = request.execute(context)
except NoSuchSlaveException as ex:
_logger.debug("requested slave does not exist: %s" % request.unit_id )
if self.server.ignore_missing_slaves:
return # the client will simply timeout waiting for a response
response = request.doException(merror.GatewayNoResponse)
except Exception as ex:
_logger.debug("Datastore unable to fulfill request: %s; %s", ex, traceback.format_exc() )
response = request.doException(merror.SlaveFailure)
response.transaction_id = request.transaction_id
response.unit_id = request.unit_id
self.send(response)
# ----------------------------------------------------------------------- #
# Base class implementations
# ----------------------------------------------------------------------- #
def handle(self):
""" Callback when we receive any data
"""
raise NotImplementedException("Method not implemented by derived class")
def send(self, message):
""" Send a request (string) to the network
:param message: The unencoded modbus response
"""
raise NotImplementedException("Method not implemented by derived class")
setup() is called when a client is connected to the server, and finish() is called when a client is disconnected. I want to manipulate these methods (setup() and finish()) in another class in another file which use the library (pymodbus) and add some code to setup and finish functions. I do not intend to modify the library, since it may cause strange behavior in specific situation.
---Edited ----
To clarify, I want setup function in ModbusBaseRequestHandler class to work as before and remain untouched, but add sth else to it, but this modification should be done in my code not in the library.
The simplest, and usually best, thing to do is to not manipulate the methods of ModbusBaseRequestHandler, but instead inherit from it and override those methods in your subclass, then just use the subclass wherever you would have used the base class:
class SoupedUpModbusBaseRequestHandler(ModbusBaseRequestHandler):
def setup(self):
# do different stuff
# call super().setup() if you want
# or call socketserver.BaseRequestHandler.setup() to skip over it
# or call neither
Notice that a class statement is just a normal statement, and can go anywhere any other statement can, even in the middle of a method. So, even if you need to dynamically create the subclass because you won't know what you want setup to do until runtime, that's not a problem.
If you actually need to monkeypatch the class, that isn't very hard—although it is easy to screw things up if you aren't careful.
def setup(self):
# do different stuff
ModbusBaseRequestHandler.setup = setup
If you want to be able to call the normal implementation, you have to stash it somewhere:
_setup = ModbusBaseRequestHandler.setup
def setup(self):
# do different stuff
# call _setup whenever you want
ModbusBaseRequestHandler.setup = setup
If you want to make sure you copy over the name, docstring, etc., you can use `wraps:
#functools.wraps(ModbusBaseRequestHandler.setup)
def setup(self):
# do different stuff
ModbusBaseRequestHandler.setup = setup
Again, you can do this anywhere in your code, even in the middle of a method.
If you need to monkeypatch one instance of ModbusBaseRequestHandler while leaving any other instances untouched, you can even do that. You just have to manually bind the method:
def setup(self):
# do different stuff
myModbusBaseRequestHandler.setup = setup.__get__(myModbusBaseRequestHandler)
If you want to call the original method, or wraps it, or do this in the middle of some other method, etc., it's otherwise basically the same as the last version.
It can be done by Interceptor
from functools import wraps
def iterceptor(func):
print('this is executed at function definition time (def my_func)')
#wraps(func)
def wrapper(*args, **kwargs):
print('this is executed before function call')
result = func(*args, **kwargs)
print('this is executed after function call')
return result
return wrapper
#iterceptor
def my_func(n):
print('this is my_func')
print('n =', n)
my_func(4)
more explanation can be found here

Does a callback execute when other function is running?

I have a conceptual doubt.
If I pass a class method as a callback function (to another program running on other thread) and I get struck in some other class method (not the callback method) eg while(True).
Will the callback ever execute?
class Bicycle(object):
__init__(self, name):
self.name = name
self.f = 0
def callback(self, push_force):
#Go ahead
self.f = push_force
def balance(self):
while True:
# Balance the Bicycle
def main():
B1 = Bicycle("Red")
external(callback=B1.callback)
while True:
B1.balance()
Not my answer, but #Bakuriu's, which is correct:
If the callback is passed to an other thread then, yes it can execute while your balance method is running... even though they will interleave in CPython due to the GIL, but they will be executed concurrently. In other Python implementations they might be executed in parallel.

Python classes: How should a built it

I am trying to create a class called ListenerVilma that has two methods: "Clock_" and "Diagnostics_". Nevertheless both methods will call inner functions. The following code shows my attempt to achieve the mentioned behavior, but when I call ListenerVilma.Clock_() the get the following error:
TypeError: unbound method Clock_() must be called with ListenerVilma instance as first argument (got nothing instead)
How should a create my class ListenerVilma???
Thanks.
#!/usr/bin/env python
import rospy
from rosgraph_msgs.msg import Clock
from diagnostic_msgs.msg import DiagnosticArray
class ListenerVilma:
"""Class that listens all topics of the file vilmafeagri"""
def Clock_(self):
"""Method that listens the topic /clock if the file vilmafeagri"""
def __init__(self):
self.listener()
def callback(self, clock):
print clock
def listener(self):
rospy.Subscriber('clock', Clock, self.callback)
def Diagnostics_(self):
"""Method that listen the topic /diagnostics from rosbag file vilmafeagri"""
def __init__(self):
self.listener()
def callback(self, diagnostics):
print diagnostics
def listener(self):
rospy.Subscriber('diagnostics', DiagnosticArray, self.callback)
if __name__ == '__main__':
rospy.init_node('listener', anonymous=True)
ListenerVilma.Clock_()
rospy.spin()
the error is in line 41 in ListenerVilma.Clock_() here your directly using the method of your class so no implicit argument is pass and a instance of ListenerVilma is expected. The solution is ListenerVilma().Clock_() this first create a instance of your class and from say instance call its Clock_ method.
Outside that, your class construction is very weird, the __init__ is used to initialize a class and a basic class construction is like this
class Foo:
"""example class"""
def __init__(self,*argv,**karg):
"""initialize this class"""
#do something with argv and/or karg according to the needs
#for example this
print "init argv", argv
print "init karg", karg
self.ultimate=42
def do_stuff(self):
"""this method do something"""
print "I am doing some stuff"
print "after 7.5 million years of calculations The Answer to the Ultimate Question of Life, the Universe, and Everything is: ", self.ultimate
def do_some_other_stuff(self,*argv,**karv):
"""this method do something else"""
print "method argv", argv
print "method karg", karg
# basic usage
test = Foo(1,2,3,key_test=23)
test.do_stuff()
test.do_some_other_stuff(7,8,9,something=32)
test.ultimate = 420
test.do_stuff()
I am not quite sure what you intentions are, but you build Clock_ and Diagnostics_ as a class, but they are not, and as right now they do nothing, if you want they to be class on their own do
class Clock_:
def __init__(self):
self.listener()
def callback(self, clock):
print clock
def listener(self):
rospy.Subscriber('clock', Clock, self.callback)
and the same with Diagnostics_, and I don't see a reason to the listener method so I would put what it does in the __init__, but maybe the rospy need it? I don't know, but for the looks of it then it should be used as
rospy.init_node('listener', anonymous=True)
Clock_()
Diagnostics_()
rospy.spin()
The Clock_ method doesn't belong to the class; it's an 'instance' method.
There are two options
In the main function: create an instance of ListenerVilma: listener = ListenerVilma(), or
In the ListenerVilma class: annotate the methods with #classmethod and make the class inherit from object: class ListenerVilma(object):. But remember, the first argument in your methods will be a reference to the class and not a reference to an instance.
The following code performs better the behavior that I wanted. :)
class ListenerVilma:
def CLOCK(self):
def clock_sub():
rospy.Subscriber('clock', Clock, clock_callback)
def clock_callback(clock):
print clock
clock_sub()
def DIAGNOSTICS(self):
def diagnostics_sub():
rospy.Subscriber('diagnostics', DiagnosticArray, diagnostics_callback)
def diagnostics_callback(diagnostics):
print diagnostics
diagnostics_sub()
if __name__ == '__main__':
rospy.init_node('listener', anonymous=True)
myVilma = ListenerVilma()
myVilma.CLOCK()
myVilma.DIAGNOSTICS()
rospy.spin()

Python: setup() vs __init__ ()for a socketserver's handler class

I am trying to define a handler class for a socketserver. When the handler class had no __init__() method defined, my server worked. The message sent by the client was written to the output window. However, when I added an __init__() method to declare a class member, my program threw an exception because RequestHandlerClass required exactly one argument, and I was passing four arguments to it. After pounding my head into a brick wall for a while, I remembered that the BaseRequestHandler class has an override-able setup() method. I declared an override for it and declared my class member inside it, and it worked.
While I have a solution to my immediate problem, I'd like to understand this. Should I never declare my own __init__() method in a request handler class? Or if I should, how should it be declared?
Here's my code:
import socketserver
import logging
import logging.config
import json
from TWMSMessageHandler import TWMSMessageHandler
class SingleTCPHandler(socketserver.BaseRequestHandler):
# def __init__(self): ## causes an error
def setup(self):
self.messageHandler = TWMSMessageHandler()
# One instance per connection. Override handle(self) to customize action.
def handle(self):
# self.request is the client connection
data = self.request.recv(1024) # clip input at 1Kb
dataString = data.decode()
print ("Received data: " + dataString)
self.request.close()
class MyTCPServer(socketserver.TCPServer):
def __init__(self, serverAddress, handler):
super().__init__(serverAddress, handler)
def handle_timeout(self):
print ("No message received in {0} seconds".format(self.timeout))
if __name__ == "__main__":
with open('TWMSHandler_log_config.json', 'rt') as f:
config = json.load(f)
logging.config.dictConfig(config)
tcpServer = MyTCPServer(("127.0.0.1", 5006), SingleTCPHandler)
tcpServer.timeout = 30
loopCount = 0
while loopCount < 5:
try:
print ("About to wait for request")
tcpServer.handle_request()
print ("Back from handle_request")
loopCount = loopCount + 1
except Exception as Value:
print ("Oops! " + str(Value))
break
I'm assuming python 2.7 since you haven't specified otherwise, this should apply to python 3.x too, however.
If you take a look at the source code (https://hg.python.org/cpython/file/2.7/Lib/SocketServer.py#l631), the BaseRequestHandler class which you are overriding takes 3 arguments besides self: request, client_address, server. If you want to override __init__ you must be compatible with this signature, unless you also override the callsite that calls __init__ from within the TCPServer inheritance chain (You don't want to do this).
Since all that function does is to save state you would otherwise have to save yourself (Or call the base function through a super call), you may as well just use setup as you are.

Cant assign thread to local variable

I have the following code in python:
class gateWay:
def __init__(self):
self.var1 = []
self.var2 = {}
self.currentThread = None
def stateProcess(self, file):
# some irrelevant code
self.currentThread = saltGatWayThread(self, file).start()
return self.var1
def stopRunning(self):
self.currentThread.proc.stop()
In addition, here the source code of the saltGatWayThread:
class saltGatWayThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
# some irrelevant code
self.proc = src.proc.Process1()
In addition, I have the following code in src/proc/__init__.py:
class Process1:
def stop(self):
# code to stop operation
In the console, I notice that self.currentThread is null.
My purpose is to save the thread in local variable, when start it. If I get an abort request, I apply
stopRunning function. This function, would take the saved thread and will do "clean" exit (finish the process of the tread and exit).
Why can't I save the thread, and use the structure of it later on?
invoke currentThread = saltGatWayThread() and then call .start(). currentThread does not contains thread instance because starts() method always returns nothing according to the threading.py source code. See source of C:\Python27\Lib\threading.py
def start(self):
"""Start the thread's activity.
It must be called at most once per thread object. It arranges for the
object's run() method to be invoked in a separate thread of control.
This method will raise a RuntimeError if called more than once on the
same thread object.
"""
if not self.__initialized:
raise RuntimeError("thread.__init__() not called")
if self.__started.is_set():
raise RuntimeError("threads can only be started once")
if __debug__:
self._note("%s.start(): starting thread", self)
with _active_limbo_lock:
_limbo[self] = self
try:
_start_new_thread(self.__bootstrap, ())
except Exception:
with _active_limbo_lock:
del _limbo[self]
raise
self.__started.wait()

Categories

Resources