Importing classes from sub-packages - help needed

I’m developing a component that can control multiple brands and models of same kind devices. Currently the component works great with one small exception - all classes for all devices as hardcoded in a single file, which is pain in the *ss when it comes to readability and maintenance, so I’ve created a sub-directory with empty __init__.py inside it and I split all the classes in separate .py files in the same sub-directory I mentioned above. The question is how to dynamically load in climate.py the classes from that sub-directory by having class name, as string value, coming from the platform config entry in configuration.yaml (like brand: 'Panasonic')? File structure and config entry are shown at the end of the topic.
Next snippet works, but it is not dynamic …

from .heatpumps.panasonic import Panasonic

Next snippet produces error: “No module named heatpumps”
The error is only in hass.io . When I run same code with same file structure locally on my PC it works fine.

# climate.py
import importlib

# module = importlib.import_module('.' + brand.lower(), 'heatpumps') #error here
module = importlib.import_module('.panasonic', 'heatpumps') #error here

# heatpump_class = getattr(module, brand)
heatpump_class = getattr(module, 'Panasonic')
ac = heatpump_class()

Other things I tried with no success:

module = importlib.import_module('.panasonic', '.heatpumps') # No module named '.heatpumps'
module = importlib.import_module('heatpumps.panasonic')  # No module named 'heatpumps'
module = importlib.import_module('.heatpumps.panasonic')  # No module named '.heatpumps'
module = importlib.import_module('irclimate.heatpumps.panasonic')  # No module named 'irclimate'

File hierarchy:
custom_components (dir)
|_ irclimate (dir)
   |_ __init__.py
   |_ climate.py
   |_ const.py
   |_ manifest.json
   |_ reproduce_state.py
   |_ heatpumps (dir)
      |_ __init__.py
      |_ acprotocol.py
      |_ panasonic.py
      |_ fujitsu.py
      |_ daewoo.py
      |_ etc …

Example ‘panasonic.py’:

class Panasonic:
  pass

Example configuration.yaml entry:

  - platform: irclimate
    name: Panasonic Air Conditioner
    target_sensor: sensor.temp_feel
    min_temp: 16
    max_temp: 30
    ac_mode: true
    target_temp: 26
    cold_tolerance: 0
    hot_tolerance: 0
    min_cycle_duration:
      seconds: 5
    keep_alive:
      minutes: 3
    initial_operation_mode: "off"
    away_temp: 24
    precision: 1.0
    topic: "cmnd/blaster/irsend"
    brand: "Panasonic"
    send_action:
      service: script.ir_raw
      data:
        data: 'send'
        room: kitchen

Have you read the documentation for import_module closely? There is a whole section on relative imports.

I suspect you need to do something like import_module('homeassistant.custom_components.irclimate.heatpumps.panasonic')

Alternatively a more straightforward approach would be to make heatpumps a pypi package. You can develop both in tandem using an editable installation before pushing the package to pypi.

This comment about a pypi package only applies if you are planning to share this custom component, otherwise you can just install heatpumps into your environment in editable mode.

I know nothing about doing this in hassio though. It is fairly trivial when using a regular virtual environment.

import_module(‘homeassistant.custom_components.irclimate.heatpumps.panasonic’)
This returns “No module named homeassistant. custom_components”

custom_components.irclimate.heatpumps.panasonic should work

But your should consider extracting heatpumps to a seperate package hosted on pypi

@ludeeus It works … So it is a problem with paths … :slight_smile: Thank you! Now buy yourself one coffee on my bill (from your pocket) :smiley: Hurray! :wink:

PS: It worked without extracting to a separate pypi package … :slight_smile: