# Python scripted module development reload feature for multiple files

**URL:** https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363
**Category:** Development
**Created:** [April 2, 2019, 8:42am UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363 "2019-04-02T08:42:52Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![michalikthomas](https://avatars.discourse-cdn.com/v4/letter/m/7cd45c/32.png) [@michalikthomas](https://discourse.slicer.org/u/michalikthomas)
#### Post date: [April 2, 2019, 8:42am UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/1 "2019-04-02T08:42:52Z")

</div>

Is there a way how to customize/override default development feature - “Reload” - behavior, during scripted module development? I separated code into multiple files but “Reload” seems to reload just the root python file, not the whole folder.

---

<div class="post-metadata">

### Author: ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)
#### Post date: [April 2, 2019, 9:23pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/2 "2019-04-02T21:23:16Z")

</div>

It’s a very good question - I did the original scripted module reload code many years ago and it took a while to sort out all the tweaks needed to get it working, so I never went back and looked into the options multiple-file reload, which is too bad because it tends to make me put more than I should in the main scripted module file.

Probably the same techniques that work for the main module would also work for imported files and maybe there’s even a way to discover the dependencies automatically and reload them all or maybe the scripted module could provide a list of code to reload. It may also be that with the python3 transition there will be new ways to do this, I haven’t looked. Would love to see a PR for this.

---

<div class="post-metadata">

### Author: ![jcfr](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/jcfr/32/17825_2.png) [@jcfr](https://discourse.slicer.org/u/jcfr)
#### Post date: [April 2, 2019, 9:55pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/3 "2019-04-02T21:55:32Z")

</div>

It may be worth revisiting the approach by looking at the autoreload module from ipython.

See [https://github.com/ipython/ipython/blob/master/IPython/extensions/autoreload.py](https://github.com/ipython/ipython/blob/master/IPython/extensions/autoreload.py)

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [April 3, 2019, 1:01am UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/4 "2019-04-03T01:01:58Z")

</div>

Reloading is implemented fully in Python, so you can override the default implementation and reload additional modules, too. Since there are usually dependencies between classes, you typically need to click reload 2-3 times to update all referenced objects in al objects.

Example:

```auto
class ValveAnnulusAnalysisWidget(ScriptedLoadableModuleWidget):
  ...
  def onReload(self):
    logging.debug("Reloading ValveAnnulusAnalysis")
    packageName='HeartValveLib'
    submoduleNames=['util', 'LeafletModel', 'SmoothCurve', 'ValveRoi', 'PapillaryModel', 'ValveModel', 'HeartValves']
    import imp
    f, filename, description = imp.find_module(packageName)
    package = imp.load_module(packageName, f, filename, description)
    for submoduleName in submoduleNames:
      f, filename, description = imp.find_module(submoduleName, package. __path__ )
      try:
          imp.load_module(packageName+'.'+submoduleName, f, filename, description)
      finally:
          f.close()
    ScriptedLoadableModuleWidget.onReload(self)

```

---

<div class="post-metadata">

### Author: ![michalikthomas](https://avatars.discourse-cdn.com/v4/letter/m/7cd45c/32.png) [@michalikthomas](https://discourse.slicer.org/u/michalikthomas)
#### Post date: [April 10, 2019, 8:00pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/5 "2019-04-10T20:00:11Z")

</div>

Thank you, @lassoan, for your example. Could you please add more information about how modules are registered and initiated within mentioned scripted module? I wasn’t able to me this work.

My scripted module structure looks as follows:

```
CustomScriptedModule/
    CustomScriptedModule.py
    CustomScriptedModuleLib/
        __init__.py
        CustomScriptedModuleWidget.py
        OtherModule1.py
        OtherModule2.py
        ...

```

Init file contains:

```
from CustomScriptedModuleWidget import *
from OtherModule1 import *
from OtherModule2 import *
...
```

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [April 10, 2019, 8:31pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/6 "2019-04-10T20:31:14Z")

</div>

Replace “HeartValveLib” by “CustomScriptedModuleLib”; ‘util’ by ‘OtherModule1’, ‘LeafletModel’ by ‘OtherModule2’, etc.

You must keep the module widget class in CustomScriptedModule.py. If you want to simplify widget creation, then choose “scripteddesigner” module template in the Extension Wizard and use Qt Designer to create your GUI.

---

<div class="post-metadata">

### Author: ![michalikthomas](https://avatars.discourse-cdn.com/v4/letter/m/7cd45c/32.png) [@michalikthomas](https://discourse.slicer.org/u/michalikthomas)
#### Post date: [April 10, 2019, 9:01pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/7 "2019-04-10T21:01:05Z")

</div>

Thanks, this works perfectly.

---

<div class="post-metadata">

### Author: ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)
#### Post date: [April 11, 2019, 7:39pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/8 "2019-04-11T19:39:49Z")

</div>

> [@lassoan](#):
>
> you can override the default implementation and reload additional modules

This looks nice @lassoan - any reason not to make `submoduleNames` an property and move this implementation into `ScriptedLoadableModuleWidget` ?

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [April 11, 2019, 7:47pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/9 "2019-04-11T19:47:41Z")

</div>

Yes, it would be nice to add this to the module base class. There could be a list of tuples set in the module widget class constructor to define package and submodule names to reload - something like this:

```
self.packagesToReload = (
  ('packageName1', ('submoduleNameA', 'submoduleNameB')),
  ('packageName2', ('submoduleNameA', 'submoduleNameB', 'submoduleNameC'))
  )
```

---

<div class="post-metadata">

### Author: ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)
#### Post date: [April 11, 2019, 8:04pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/10 "2019-04-11T20:04:53Z")

</div>

Sounds good - I’ll probably do that next time I run into this. (Unless someone beats me to it!)

---

<div class="post-metadata">

### Author: ![Alex\_Vergara](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/alex_vergara/32/15205_2.png) [@Alex\_Vergara](https://discourse.slicer.org/u/Alex_Vergara)
#### Post date: [July 29, 2019, 1:53pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/11 "2019-07-29T13:53:23Z")

</div>

IDK if you are aware that the package imp is [deprecated](https://docs.python.org/3/library/imp.html) in python since version 3.4 and will be removed. it is recommended to move to importlib library. However, I did not succeed yet to make it work properly while reloading.

---

<div class="post-metadata">

### Author: ![lassoan](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/lassoan/32/13_2.png) [@lassoan](https://discourse.slicer.org/u/lassoan)
#### Post date: [July 29, 2019, 6:29pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/12 "2019-07-29T18:29:36Z")

</div>

Thank you for looking into this. Probably we’ll get to this when imp is actually removed, starts to misbehave, or we need to rework module loading for some other reason anyway.

---

<div class="post-metadata">

### Author: ![pieper](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pieper/32/8_2.png) [@pieper](https://discourse.slicer.org/u/pieper)
#### Post date: [April 21, 2020, 4:55pm UTC](https://discourse.slicer.org/t/python-scripted-module-development-reload-feature-for-multiple-files/6363/13 "2020-04-21T16:55:34Z")

</div>

In some experimental code I found a handy workaround for this. I put this in my module’s Logic class so that every time I reload the module I get a fresh copy of the Lib code.

```auto
  def __init__ (self):
    import VudoLib, VudoLib.Vudo
    self.VudoModule = importlib.reload(VudoLib.Vudo)

```

It should probably be made conditional on being in debug mode, since it loads the Lib twice at startup, but that’s usually a very small penalty in practice. The import has to happen before the reload because reload only works on something that’s already been loaded. I didn’t find anything that actually does the initial load via an api.
