I would like to import optional GUI elements defined in separate .py files and add/remove these dynamically from the main GUI. The optional elements are defined in a text configuration file and thus the file names are not known in advance. My original idea was to impose a common format - the main class would be identically named in all module files. I found that the simplest implementation of this behaves in an unexpected way. Although the imported objects appear to have distinct names, there is in fact cross-talk. This demonstrates the issue and a workaround that I found on SE (commented out): from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.floatlayout import FloatLayout from kivy.uix.button import Button from kivy.lang import Builder import importlib Builder.load_string(''' <MainWidget>: orientation: 'vertical' BoxLayout: Button: text: "Load Mod 1" on_press: root.load_module(self.text) Button: text: "Load Mod 2" on_press: root.load_module(self.text) Button: text: "Unload all" on_press: dock.clear_widgets() FloatLayout: id: dock ''') class MainWidget(BoxLayout): def load_module(self, hint): self.ids.dock.clear_widgets() if "1" in hint: self.module = importlib.import_module("Mod1").Module()#PROBLEMATIC #module = importlib.import_module("Mod1") #class_ = getattr(module, "Module1") #self.module = class_() if "2" in hint: self.module = importlib.import_module("Mod2").Module()#PROBLEMATIC #module = importlib.import_module("Mod2") #class_ = getattr(module, "Module2") #self.module = class_() self.ids.dock.add_widget(self.module) class MyApp(App): def build(self): return MainWidget() if __name__ == '__main__': MyApp().run() Mod1.py: from kivy.uix.floatlayout import FloatLayout from kivy.lang import Builder Builder.load_string(''' #<Module1>: <Module>: #PROBLEMATIC size_hint: None, None size: self.parent.size if self.parent else self.size pos: self.parent.pos if self.parent else self.pos Button: size_hint: None, None width: self.parent.width / 3 height: self.parent.height pos: self.parent.pos text: "Mod 1" on_press: print(root); print([x for x in dir(root) if 'method' in str(x)]) ''') #class Module1(FloatLayout): class Module(FloatLayout): #PROBLEMATIC def __init__(self, **kwargs): super(FloatLayout, self).__init__(**kwargs) def dummymethod1(self): pass Mod2.py: from kivy.uix.floatlayout import FloatLayout from kivy.lang import Builder Builder.load_string(''' #<Module2>: <Module>: #PROBLEMATIC size_hint: None, None size: self.parent.size if self.parent else self.size pos: self.parent.pos if self.parent else self.pos Button: size_hint: None, None width: self.parent.width / 3 height: self.parent.height pos: (self.parent.x + self.parent.width / 2) , self.parent.y text: "Mod 2" on_press: print(root); print([x for x in dir(root) if 'method' in str(x)]) ''') #class Module2(FloatLayout): class Module(FloatLayout): #PROBLEMATIC def __init__(self, **kwargs): super(FloatLayout, self).__init__(**kwargs) def dummymethod2(self): pass It appears that although the modules have distinct names Mod1 and Mod2, the main class having the same name is a problem. Once both modules have been imported at least once, both appear in the GUI regardless which one is actually activated. Although my workaround works to prevent this unwanted behaviour, I would like to know what causes it. Is this to do with how importing works in Python in general, or a Kivy specific issue? Is there another way to deal with this that would allow for identically-names classes in otherwise distinct modules? Continue reading...