4

Here is the error:

TypeError: __init__() takes exactly 1 argument (3 given)
ERROR:root:Exception in callback <tornado.stack_context._StackContextWrapper object at 0x1017d4470>
Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/tornado-2.4.1-py2.7.egg/tornado/ioloop.py", line  421, in _run_callback
    callback()
  File "/Library/Python/2.7/site-packages/tornado-2.4.1-py2.7.egg/tornado/iostream.py", line 311, in wrapper
    callback(*args)
  File "/Library/Python/2.7/site-packages/tornado-2.4.1-py2.7.egg/tornado/httpserver.py", line 268, in _on_headers
    self.request_callback(self._request)
  File "/Library/Python/2.7/site-packages/tornado-2.4.1-py2.7.egg/tornado/web.py", line 1395, in __call__
    handler = spec.handler_class(self, request, **spec.kwargs)
TypeError: __init__() takes exactly 1 argument (3 given)

And here is the code:

class IndexHandler(tornado.web.RequestHandler):
    def __init__(self):
        self.title = "Welcome!"

    def get(self):
        self.render("index.html", title=self.title)

I've simplified the code down to the above, and I am baffled as to why this is producing that error. I must be doing something wrong, but I have no idea what (3 Arguments passed???...uhmm?)

Note: the title variable is merely the <title>{{ title }}</title> in my index.html template.

I am running Python 2.7.3, in 32 Bit version in order to work with Mysqldb-Python. As you can see, my Tornado version is 2.4.1. I am also running on OSX Lion (if that makes any difference...) Maybe a compatibility issue that is ultimately producing this error?

All help is appreciated in debugging this. Thank you.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Friendly King
  • 2,396
  • 1
  • 23
  • 40

2 Answers2

9

@Princess of the Universe is right, but maybe this needs a bit of elaboration.

Tornado is going to call __init__ on RequestHandler subclasses with the parameters application, request, **kwargs, so you need to allow for that.

You can do this:

def __init__(self, application, request, **kwargs):
    self.title = "Welcome!"
    super(IndexHandler, self).__init__(application, request, **kwargs)

Which means your IndexHandler class is now initialized with the same signature as the parent class.

However, I would favour the initialize method, which Tornado provides for this purpose:

def initialize(self):
    self.title = "Welcome!"
Cole Maclean
  • 5,627
  • 25
  • 37
  • Thank you for your explanation! I am just learning Tornado and this made complete sense to me. Very helpful. – Friendly King Feb 16 '13 at 18:31
  • 4
    Tornado makes no public documentation about `RequestHandler.__init__`, and therefore no backwards compatibility contract. I would consider the `initialize` the only valid approach, for now at least. – Ying Xiong Apr 28 '15 at 22:46
1

You are overriding

__init__()

in an inappropriate way.

See

http://www.tornadoweb.org/documentation/web.html

The signature is

class tornado.web.RequestHandler(application, request, **kwargs)[source]

It is clear that you have to provide the same API for the constructor of the derived class.

  • Would you mind elaborating a little on what you mean when you say "you have to provide the same API for the constructor of the derived class"? For instance, how would I go about properly "overriding" `__init__`? – Friendly King Feb 16 '13 at 06:32
  • You have a significant lack in understanding programming and reading answers. Your __init__() must provide the same parameter list as the __init__() of the base class which is clearly (application, request, **kwargs) –  Feb 16 '13 at 06:49
  • I apologize for not quite grasping the basics of Tornado yet, as I have just started to learn it; however, your answer, in conjunction with Cole's, now makes sense to me. Thank you. – Friendly King Feb 16 '13 at 18:33
  • This is a dead link. – maxywb Apr 27 '16 at 19:35