Question: I would like to import optional GUI elements defined in separate Mod1.py/Mod2.py/etc files and add/remove these dynamically from the main GUI. The separate files that define these optional GUI elements, contain kv strings. In my use case, these GUI elements can be unloaded/reloaded multiple times. I discovered that if I have identically named classes in the Modx.py files, this creates cross-talk between the modules because Builder.load_string works cumulatively. The background to this discovery is here - Importing multiple modules containing identically named class in python Kivy Builder documentation suggests that a given kv string can be selectively unloaded later if a pseudo filename is supplied e.g. Builder.load_string("""<kv string>""", filename="myrule.kv") and later to unload - Builder.unload_file("myrule.kv") However when I try this, it appears to work only the first time a module is unloaded and another one is loaded. After that the optional GUI elements no longer appear when reloaded. The following example demonstrates this. 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() Builder.unload_file("foo.kv") if "1" in hint: self.module = importlib.import_module("Mod1").Module() if "2" in hint: self.module = importlib.import_module("Mod2").Module() 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(''' <Module>: 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)]) ''', filename="foo.kv") class Module(FloatLayout): 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(''' <Module>: 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)]) ''', filename="foo.kv") class Module(FloatLayout): def __init__(self, **kwargs): super(FloatLayout, self).__init__(**kwargs) def dummymethod2(self): pass  I would like to know if there is a way to make this work properly. Perhaps I am missing something about the way Kivy builder functions?

Answer: I think the importlib will not import a module if it has already been loaded. In that case, you can use importlib.reload(). Try modifying your MainWidget class to do that. Something like: class MainWidget(BoxLayout): def __init__(self): self.current_module1 = None self.current_module2 = None super(MainWidget, self).__init__() def load_module(self, hint): self.ids.dock.clear_widgets() Builder.unload_file("foo.kv") if "1" in hint: if self.current_module1: self.current_module1 = importlib.reload(self.current_module1) else: self.current_module1 = importlib.import_module("Mod1") self.module = self.current_module1.Module() if "2" in hint: if self.current_module2: self.current_module2 = importlib.reload(self.current_module2) else: self.current_module2 = importlib.import_module("Mod2") self.module = self.current_module2.Module() self.ids.dock.add_widget(self.module)