Here in given code it is passing class name i.e. MyRequestHandler to TCP and also after taking class name as argument what does it do with that.So my question is that can class name be used as argument and also class name doesn't refer to anything so how is it possible???i apologize for silly ques!!
from SocketServer import (TCPServer as TCP,
StreamRequestHandler as SRH)
from time import ctime
HOST = ''
PORT = 21567
ADDR = (HOST, PORT)
class MyRequestHandler(SRH):
def handle(self):
print '...connected from:',self.client_address
self.wfile.write('[%s] %s' % (ctime(),
self.rfile.readline()))
tcpServ = TCP(ADDR, MyRequestHandler)
print 'waiting for connection...'
tcpServ.serve_forever(
Absolutely you can pass a class name as an argument to a function:
>>> class A():
... def __init__(self):
... print "an object from class A is created"
...
>>> def hello(the_argument):
... x = the_argument()
...
>>> hello(A)
an object from class A is created
You aren't passing in the name of a class, you are passing in a reference to the class. A class is an object just like everything else. Think of it as a function that returns another object. You can pass a class as an argument just like you can pass a function, a string, or any other object.
As for what the called function can do with it -- it create create instances of that class. In this case, the called function doesn't really care what class it uses, as long as it implements a particular interface. So, the called function doesn't ever see the name of the class, it's just told how to create an instance of it (by virtue of being given a reference to the class)
In the case of a server, it needs to create a new instance of some object for every connection to the server. So, you give it the class you want it to use, and it creates instances for each connection. This lets the server create the objects when it needs them, rather than requiring you to create them ahead of time.
can class name be used as argument?
Yes. but in your code you are not passing a class name to the TCP constructor, you are passing a request handler to the constructor.
also class name doesn't refer to anything so how is it possible?
As mention above, you are passing a request handler to the Tcp constructor, your request handler refers to an action which TCP server will use to handle the incoming request. So it does refer to something.
yes you can pass to class args or function parameter
1 - using type(object)
2 - class Name
==>>passing ClassA to to ClassB and fname as parameters
class ClassA(object):
def __init__(self,):
pass
class ClassB(object):
def __init__(self, arg):
print(type(arg))
pass
def fname(arg):
print(type(arg))
pass
valueA: ClassA = ClassA()
ClassB(type(valueA))
ClassB(ClassA)
fname(type(valueA))
fname((ClassA))
Related
I have this python script which has a listener class and a main class. A serial stream is created in the main class and a listener instance is created in the main class. The whole purpose of the listener is to send a message on the serial port when a listened property has changed. The problem is that the listener doesn't have access to the output stream created in the main class. The listener does an abrupt return when trying to execute the outputStream.write statement How can I give the listener access to the output stream?
import purejavacomm
import java.beansSensorListener
class MyListener(java.beans.PropertyChangeListener):
def propertyChange(self, event):
if (< some property has changed >) :
self.outputStream.write(message) # send notice on serial port
return
class MainClass(jmri.jmrit.automat.AbstractAutomaton) :
def __init__(self) :
self.portID = purejavacomm.CommPortIdentifier.getPortIdentifier("COM3")
self.port = self.portID.open("SerialCom", 50)
self.outputStream = self.port.getOutputStream()
return
def init(self) :
myListener = MyListener()
deviceList = devices.getNamedBeanSet()
for device in deviceList :
device.addPropertyChangeListener(myListener)
return
a = MainClass()
a.start();
It seems that really MyListener should either have a stream passed into the constructor or the callback (using lambda expression).
First, which is probably the cleanest way, would look like this:
def init(self) :
myListener = MyListener(self.outputStream)
Second version: device.addPropertyChangeListener(lambda x: myListener(x, self.outputStream)) Both need changes in the MyListener class to either constructor, or definition of propertyChange.
If you are set of sharing an instance of here are two options.
If you can modify arguments to MyListener constructor you pass in instance of MainClass to it:
def init(self) :
myListener = MyListener(self)
If not, a little bit more hacky way of doing this is by making MainClass a singelton (see example here), and then calling it's constructor within MyListener
I have a problem with overriding the init method of the thread class.
I only need it to take a socket that i pass to the init method when I instantiate the thread object.
The code of the thread class is:
class client_handle(threading.Thread):
conne = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def __init__(self, conne=None):
threading.Thread.__init__(self, conne=conne)
When i create a client_handle object i write:
socket_conn, addr = s.accept()
client_thread = client_handle(socket_conn)
I also searched in other posts but i couldn't solve my problem.
You need to assign conne manually as attribute of the instance. Passing it as argument to Thread.__init__ won't work (would be set as the group-argument of the Thread-class).
from threading import Thread
class ClientHandle(Thread):
def __init__(self, conne=None):
super().__init__() # Python 3
self.conne = conne
Thread.__init__ doesn't have a parameter named conne, so you have to pass the value as a positional argument instead.
def __init__(self, conne=None):
threading.Thread.__init__(self, conne)
Incidentally, the class attribute client_handle.conne doesn't seem to serve any purpose; you can probably get rid of it.
Update: passing a socket to Thread.__init__ in particular is clearly wrong, but this applies to any attempt to "invent" a parameter name like conne for a method that doesn't have a parameter named conne.
I want to have a list of classes in the base class file which holds the derived classes as they are being created in runtime:
BaseClass.py:
# This is a list of objects to populate, holds classes (and not instances)
MyClassesList=[]
class MyBase(object):
name='' #name of the specific derived class
def __init__(self):
pass
This is a real world example:
I am not able to modify any derived classes code so I want to maintain a list of added servers in the base class and then access this list in runtime
# Populate the Servers list automatically.
# This is a list of available servers to choose from, holds classes (and not instances)
Servers=[]
class ServerBase(object):
name='' #name of the specific server class, for each server class
def __init__(self):
self.connected = False
def __del__(self):
self._disconnect()
def connect(self):
DBG("connect called for server {self.name}, is already connected: {self.connected}")
if self.connected: return
self._connect()
self.connected = True
def get_data(self):
self.connected or self.connect()
data=''
# We're obligated to read the data in chunks.
for i in range(100):
data += self._get_data()
return data
def _connect(self):
raise NotImplementedError("Interface Function Called")
def _disconnect(self):
raise NotImplementedError("Interface Function Called")
def _get_data(self):
raise NotImplementedError("Interface Function Called")
Assuming what you want is a list of derived class objects (though no idea why you would want that) created at runtime.
When creating an object of a Derived class, in your Base Class's __init__ function, the self, being passed in would be the Derived class's object , Unless the derived class overrides the __init__() function and does not call super().__init() , in which case, I am not sure if it would be possible.
If you control the derived classes , you can call super().__init__() in the derived class' __init__() and then have the __init__() function save that object to the list as you want.
You can use that self to add to the list you want.
A simple test like below may help you -
class CA:
def __init__(self):
print('Type - ' + str(type(self)))
>>> CA()
Type - <class '__main__.CA'>
<__main__.CA object at 0x006B9830>
class CASub(CA):
pass
>>> CASub()
Type - <class '__main__.CASub'>
<__main__.CASub object at 0x006B9890>
There may be better ways to do it, this would be one way.
I am using a simpleWebSocket server class and have a 1 second interval timer that I would like to call methods in a couple of different classes.
the wsscb() class is the handler for the SimpleWebSocketServer(), how can I call a method from the wss() object from another object such as the udt() timer ?
Calling wss.wsscb().myfunc() results in an error: "AttributeError: 'SimpleWebSocketServer' object has no attribute 'wsscb'"
calling wsscb.myfunc() results in: TypeError: unbound method myfunc() must be called with wsscb instance as first argument (got nothing instead)
class wsscb(WebSocket):
def __init__(self, server, sock, address):
WebSocket.__init__(self, server, sock, address)
def myfunc(self):
self.send('some data')
def handleMessage(self):
pass
def handleConnected(self):
pass
class udt(Thread):
def __init__(self, event):
Thread.__init__(self)
self.stopped = event
def run(self):
while not self.stopped.wait(1.00):
wss.wsscb().myfunc()
xxx.yyy()().anotherfunc()
## Main
wss = SimpleWebSocketServer('', 4545,wsscb)
## Start Timer
stopFlag = Event()
self.udt = udt(stopFlag)
self.udt.start()
wss.serveforever()
There are a couple problems.
wss.wsscb() isn't valid. Typing that means you're trying to call a function in wss called wsscb(). wss is a SimpleWebSocketServer, and there is no function called wsscb(). A function is not the same as calling an object.
wsscb() won't work either, because in your class, you're saying it's takes a WebSocket object, which I assume takes some parameters, so you need to pass it those.
I think it would be best to make a subclass of SimpleWebSocketServer (instead of WebSocket), and put your custom function in there. Your comment says "wsscb() is a subclass of SimpleSocketServer", but it is not. It's a subclass of WebSocket.
You also never created an object of type wsscb.
If you can explain what you're specifically trying to achieve, and what myfunc() is, we may be able to help more
Also, you really shouldn't subclass Thread. Scrap the udt class you made and instead
def myfunc(wsscb_object):
while True:
time.sleep(1)
wsscb_object.myfunc()
#whatever else you want
wsscb_object = wsscb(#pass the parameters)
thread = Thread(target=myfunc, args=(some_socket))
thread.start()
You may also want to read up more on inheritance:
python subclasses
http://www.jesshamrick.com/2011/05/18/an-introduction-to-classes-and-inheritance-in-python/
Using inheritance in python
I'm implementing a python application which is using ThreadingTCPServer and a custom subclass of BaseRequestHandler. The problem with this is that the ThreadingTCPServer seems to automatically spawn threads and create instances of the handler, calling their handle() function. However this leaves me with no way to pass data to the handler other than using global variables or class variables, both of which seem hackish. Is there any better way to do it?
Ideally this should be something like:
class ThreadedTCPServer(ThreadingTCPServer):
def process_request(self, *args, **kwargs):
ThreadingTCPServer.process_request(self, data, *args, **kwargs)
with the handler like
class ThreadedTCPRequestHandler(BaseRequestHandler):
def handle(self,data):
#do something with data
I stumbled upon the very same thing. My solution was the following:
class ThreadedTCPRequestHandler(SocketServer.StreamRequestHandler):
def handle(self):
print(self.server.mycustomdata)
class ThreadedTCPServer(SocketServer.ThreadingTCPServer):
pass
server = ThreadedTCPServer((args.host, args.port), ThreadedTCPRequestHandler)
server.mycustomdata = 'foo.bar.z'
server.serve_forever()
The RequestHandler is called with a server object as a third parameter, and it is saved as self.server attribute, so you can access it. If you would set this attribute to a callable, you could easily call it, too:
def handle(self):
mycustomdata = self.server.mycustomdata()
The first answer worked for me, but I think it is cleaner to alter the __init__ method and pass the attribute in the constructor:
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
def __init__(self, host_port_tuple, streamhandler, Controllers):
super().__init__(host_port_tuple, streamhandler)
self.Controllers = Controllers
Note the third parameter 'Controllers' in the constructor, then the call to super without that parameter, then setting the new attribute Controllers to the property self.Controllers. The rest of the class is unchanged. Then, in your Requesthandler, you get access to the parameter using the 'server' attribute, as described above:
def handle(self):
self.Controllers = self.server.Controllers
<rest of your code>
It's much the same as the answer above but I find it a little cleaner because the constructor is overloaded and you simply add the attribute you want in the constructor:
server = ServerInterface.ThreadedTCPServer((HOST, PORT), ServerInterface.ThreadedTCPRequestHandler, Controllers)
Since handle is implemented by your BaseRequest subclass, it can get the data from itself without having it passed by the caller. (handle could also be a callable attribute of the request instance, such as a lambda—explicit user_data arguments are normally unnecessary in idiomatically designed python.)
Looking at the SocketServer code, it should be straightforward to override finish_request to pass the additional data to your BaseRequestHandler subtype constructor which would store it in the instance for handle to use.