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.
Related
I'm trying to override a python class (first time doing this), and I can't seem to override this method. When I run this, my recv method doesn't run. It runs the superclasses's method instead. What am I doing wrong here? (This is python 2.7 by the way.)
import socket
class PersistentSocket(socket.socket):
def recv(self, count):
print("test")
return super(self.__class__, self).recv(count)
if __name__ == '__main__':
s = PersistentSocket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 2300))
print(s.recv(1)
The socket type (officially socket.SocketType, though socket.socket happens to be the same object) makes the strange choice of implementing recv and a few other methods as instance attributes, rather than as normal methods in the class dict. In socket.SocketType.__init__, it sets a self.recv instance attribute that overrides the recv method you tried to define.
Picking on the explanation from #user2357112, one thing that seems to have helped is to do a delattr(self, 'recv') on the class constructor (inheriting from socket.SocketType) and then define you own recv method; for example:
class PersistentSocket(socket.SocketType):
def __init__(self):
"""As usual."""
delattr(self, 'recv')
def recv(self, buffersize=1024, flags=0):
"""Your own implementation here."""
return None
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))
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.
I have this class:
from threading import Thread
import time
class Timer(Thread):
def __init__(self, interval, function, *args, **kwargs):
Thread.__init__()
self.interval = interval
self.function = function
self.args = args
self.kwargs = kwargs
self.start()
def run(self):
time.sleep(self.interval)
return self.function(*self.args, **self.kwargs)
and am calling it with this script:
import timer
def hello():
print \"hello, world
t = timer.Timer(1.0, hello)
t.run()
and get this error and I can't figure out why: unbound method __init__() must be called with instance as first argument
You are doing:
Thread.__init__()
Use:
Thread.__init__(self)
Or, rather, use super()
This is a frequently asked question at SO, but the answer, in brief, is that the way you call your superclass's constructor is like:
super(Timer,self).__init__()
First, the reason you must use:
Thread.__init__(self)
instead of
Thread.__init__()
is because you are using the class name, and not an object (an instance of the class), so you cannot call a method in the same way as an object.
Second, if you are using Python 3, the recommended style for invoking a super class method from a sub class is:
super().method_name(parameters)
Although in Python 3 is possible to use:
SuperClassName.method_name(self, parameters)
It is an old style of syntax that is not the prefer style.
You just need to pass 'self' as an argument to 'Thread.init'. After that, it works on my machines.