1

I'm fairly new to Python and currently I'm running a few examples to understand how things work, but I got stuck in one of the steps.

I have a class with several attributes in it, and an __init__(self) constructor, something like this:

class A:
  # Some attributes here
  a = None;
  b = None;
  ...

  def __init__(self):
    # Do some stuff here

Further, I have another class which inherits from 2 classes: the above A and SocketServer.BaseRequestHandler (library).

class TCPHandler(A, SocketServer.BaseRequestHandler):
  def handle(self):
    # Do some other stuff here

Basically this will trigger the handle() method once it receives a TCP request, but my question is much simpler than that. When I declare a TCPHandler object, I do it that way:

server = SocketServer.TCPServer('localhost', 9191), TCPHandler)
server.serve_forever()

This, however, seems to try invoking an A class' constructor with 4 arguments (which I presume the SocketServer.BaseRequestHandler has):

TypeError: __init__() takes exactly 1 argument (4 given)

So in A I added another constructor with 4 arguments:

  def __init__(self, a=None, b=None, c=None, d=None):
    # Do some other stuff here

Now this constructor seems to be triggered, however, the RequestHandler.handle() method is never called upon an arriving TCP connection.

Why is the handle() method never called in this situation?

---- EDIT ----

This would be a short and complete program that would illustrate the behavior I explained:

import sys
import SocketServer

class A:
  a = ''
  b = ''
  c = ''

  def load_config(self):
    a = 'a'
    b = 'b'
    c = 'c'

  def __init__(self):
    self.load_config()

  def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True, debug=True):
    self.load_config()

class TCPHandler(A, SocketServer.BaseRequestHandler):
  def handle(self):
    print "I reached handle()!!"

if __name__ == "__main__":
  server = SocketServer.TCPServer(('localhost', 9999), TCPHandler)
  server.serve_forever()
  • If the 5 argument constructor wasn't added, the error above would be shown.
  • If the 5 argument constructor is added, the I reached handle()!! message is never shown (therefore, handle() is not being triggered).
nKn
  • 13,691
  • 9
  • 45
  • 62
  • Your program is failing because `Do some other stuff here` is wrong. You should do some more other stuff. :) Please create a short, **complete** program that demonstrates the error you are having. – Robᵩ Sep 11 '14 at 21:55
  • 1
    Side note, in your edited example, python doesn't overload methods. The second `__init__(self, server_address, RequestHandlerClass, bind_and_activate=True, debug=True)` overwrites the previous `__init__(self)` – tdelaney Sep 11 '14 at 22:34
  • @tdelaney That explains a lot, thanks for the note. So assuming that now I have another class that inherits from `A`, I cannot call the new `__init__` method as it would instantiate the `SocketServer.BaseRequestHandler` object. I'll possibly make another method to be called just from this new class as a 'initiator'. – nKn Sep 11 '14 at 22:40
  • @nKn if you inherit from A, you want that class to call init because you do want BaseRequestHandler initialized too. But your plan to have an alternate initializer is reasonable. – tdelaney Sep 12 '14 at 03:58

1 Answers1

1

Your program does this:

def __init__(self, a=None, b=None, c=None, d=None):
  # Do some other stuff here

It should probably do this:

def __init__(self, a=None, b=None, c=None, d=None):
  A.__init__(self)
  SocketServer.BaseRequestHandler.__init__(self, a, b, c, d)
  # Do some other stuff here
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • If someone wants to edit my answer to include a reference to `super()`, feel free. – Robᵩ Sep 11 '14 at 21:57
  • Thanks, that worked. However, I'm not able to fully understand why should the `SocketServer.BaseRequestHandler`'s constructor be called explicitely (probably I'm too accostumed to other languages :-(), I mean, `TCPHandler` inherits from `A` and `SocketServer.BaseRequestHandler`, right? Shouldn't constructors be called implicitly one after the other? – nKn Sep 11 '14 at 22:11
  • Even it's working now, I added a short and complete program to illustrate what I meant (maybe it helps someone else). – nKn Sep 11 '14 at 22:16
  • 2
    @nKn In Python, you have to explicitly call the base class's `__init__`. [More info on why.](http://stackoverflow.com/q/3782827/99377) – Jon-Eric Sep 11 '14 at 22:21