1

I have small aiohttp server that takes a string from user, passes it through two Python classes to function written in C++ with Boost.Python library.

Travel of the string (from user input): browser -> wsgi -> aiohttp -> Handler class -> Manager class -> C++ library

After successfully writing and testing aiohhtp server and Manager Python class I have started writing Handler Python class. Code:

# ----------- handler.py ----------------
import manager
class Handler:
    manager = manager.manager()
    func = manager.func
    async def handle(self, string):
        return await self.manager.execute(self.func, string)
# ------------ manager.py ----------------
import boost_module
def func(string):
    return boost_module.cpp_func(string)
class Manager:
    async def execute(self, func, string):
        return func(string)

When I run aiohttp server as always, TypeError: func() takes 1 positional argument but 2 were given raises in Manager.execute method. I have tried to debug it with Pycharm and by just print(string), but on every step (inside every called function) string variable contain just a string.

Then I have tried to change manager.func signature:

# ------------ manager.py ---------------
def func(*args):
    print(args)

And it outputs (<handler.Handler object at x...>, 'string').

How could it be?

How to fix it (not just string = args[1]) ?

P.S. sorry for bad title. I just don't know how to shortly describe what is going on.

P.P.S. Code above isn't the original code. I have rewritten it to focus on the problem, and it can contain some errors because it's not tested.

UPDATE

I can reproduce this error with this simple Python script:

def func(string):
    print(string)
class Manager:
    async def execute(self, func, string):
        print(self, func, string)  # point "A"
        return func(string)  # point "B"
class Handler:
    manager = Manager()
    func = func
    async def handle(self, string):
        return await self.manager.execute(self.func, string)
if __name__ == '__main__':
    import asyncio
    asyncio.get_event_loop().run_until_complete(
        Handler().handle('string'))

If I'm running this script, it prints to console this string (point "A"):

<__main__.Manager object at 0x7f5880966208> <bound method func of <__main__.Handler object at 0x7f58809664a8>> string

.. and then raises an error (point "B"):

TypeError: func() takes 1 positional argument but 2 were given

It isn't duplicate with this this question

Illia Ananich
  • 353
  • 4
  • 16
  • 2
    Aren't you missing some `self` arguments in your methods? – Vincent Jun 15 '17 at 16:12
  • 1
    I believe the solution would be to do `func = staticmethod(manager.func)` but that isn't obvious by the marked duplicate... @JimFasarakisHillard are you sure that's the best dup target? – Tadhg McDonald-Jensen Jun 15 '17 at 16:54
  • @JimFasarakisHillard I have updated the question and I doesn't understand how your proposed question can be the same. – Illia Ananich Jun 15 '17 at 17:08
  • @TadhgMcDonald-Jensen `manager.func` isn't the method - it's a function from another module (if you a talking about first code sample). Why is this working? – Illia Ananich Jun 15 '17 at 17:11
  • 1
    any python function placed in a class definition is a method - doesn't matter where it comes from. So since you have `func = manager.func` in the class defintion and later `self.func` you are using it as a method, you can remove the method behaviour by making it a `staticmethod`. – Tadhg McDonald-Jensen Jun 15 '17 at 17:39
  • @TadhgMcDonald-Jensen It really helps! Thank you! That the real answer on my question. – Illia Ananich Jun 15 '17 at 18:28

0 Answers0