Import class in AppDaemon fails due "class takes no arguments"

Hello,

in the past I did a thing or two with Appdaemon and never felt the need of splitting my code in classes due the simplicity of the tasks. Now I am working on a more complex app and encountered an issue.

I split my app into 2 classes and as soon I want to create an instance of class AppDaemon tell’s me that my parameters are wrong:

Structure:
appdaemon_import\

  • appdaemon_import.py
  • second.py

appdaemon_import.py:

from second import SecondClass 
import hassapi as hass


class main(hass.Hass):
    def initialize(self):
        self.log("Starting...")

        second = SecondClass(self)

second.py:

class SecondClass:
    def __init(self, param):
        self.param = param

apps.yaml:

appdaemon_import:
  module: appdaemon_import
  class: main

Error message:

2022-01-26 16:40:01.236977 WARNING appdaemon_import: ------------------------------------------------------------
2022-01-26 16:40:01.236181 WARNING appdaemon_import: Traceback (most recent call last):
File “/usr/lib/python3.9/site-packages/appdaemon/app_management.py”, line 165, in initialize_app
await utils.run_in_executor(self, init)
File “/usr/lib/python3.9/site-packages/appdaemon/utils.py”, line 308, in run_in_executor
response = future.result()
File “/usr/lib/python3.9/concurrent/futures/thread.py”, line 52, in run
result = self.fn(*self.args, **self.kwargs)
File “/config/appdaemon/apps/appdaemon_import/appdaemon_import.py”, line 9, in initialize
second = SecondClass(self)
TypeError: SecondClass() takes no arguments

But the class “SecondClass” has required constructor arguments!

Any suggestions?

–4k

I would recommend that you break the app up into multiple AD apps. You will have a lot more success doing that than trying to make one large app with multiple classes. There could also be some performance considerations when trying to create one large app vs. multiple smaller apps.

Thank you for your advise.

However I am a bit dissapointed because the behaviour of imports is slighty different to the Python as I know it. Sems like I need to adapt…

The way that AD was designed with being multi-threaded and having a priority and dependency system, you pretty much have to adapt. If you’d like to discuss your application in more detail and different options for design patterns, feel free to join the AD discord channel and we’d be glad to help you out at a more granular level once we understand what you’re trying to accomplish.

1 Like

Should be

def __init__(self, param):

Not

def __init(self, param):

To use your own custom classes I suggest Global Module

If you want to use classes that are other apps I suggest self.get_app

Hi @viertausend,
I had a similar idea in mind and ran into the same issue. My solution was multiple classes in one .py file. Not as clean as I’d like but better than multiple apps or a huge class.

Hi there,

Splitting code in multiple .py files is totally possible, I managed to do this in ControllerX, a set of multiple AppDaemon apps with lots of classes that are just helpers for the apps.

Someone asked a similar question in the past, and this is what I answered: Strategies for writing more complex Appdaemon code? - #2 by xaviml

Regards,
Xavi M.

Okay that motivated me to try again. It worked for me now with all files in the same directory.
earlier I tried something like:

> .../apps/controller/mainApp.py

and I wanted to import from

.../apps/controller/features/baseFeature.py
.../apps/controller/features/feature1.py
.../apps/controller/features/feature2.py

where features1/2 would inherit from baseFeature but it seemed like something went wrong there.

Now everything is in:
> .../apps/controller
and it works fine.

1 Like