Is it possible to split a python extension into multiple Files?

Hi everyone,

I have been working on a python extension for slicer, but the .py file has started getting rather large, and I wanted to break it into more digestible chunks.

Is it possible to move the Widget and Logic classes to different files and import them from the main file?

Ideally my project structure would look something like this:

/Extension
|-- Extension.py
|-- ExtensionWidget.py
|-- ExtensionLogic.py

Where I import ExtensionWidget and Extension logic into the main Extension file.

I tried setting this up, but Slicer doesn’t seem to be detecting the UI or the Logic as a part of the main extension. And help is appreciated, thanks!

Yes, you can make a lib folder and put your extra py files in that. There are lots of examples in the extension index, but here a simple one. Slicer looks at all the .py files in the top level and tries to interpret them as modules.

1 Like

Looking at it now the link I sent is maybe not the best example but lots of modules in that repo follow the same pattern.

1 Like

Here is another example: SlicerHeart/ValveAnnulusAnalysis at master · SlicerHeart/SlicerHeart · GitHub

1 Like

Thank you both so much for the help, I was able to figure everything out with this advice!

For splitting the Widget and Logic classes to different files, I just had to make sure that I pointed to the right locations from the main plugin file as well!

e.g.
Module.py

import ModuleLib.Widget as mw

class Module(ScriptedLoadableModule):
    ...

ModuleWidget = mw
1 Like

Just noticed something that doing this actually caused, and was wondering if there was a way to fix/work around it…

Now when I reload my module using the developer tools, it doesn’t seem to update the files that are imported from other locations, just the main module file. Is there a way to tell slicer it needs to reload these files too when it updates?

Thanks!

Yes, if you split up your module into multiple files then reloading becomes more complex. In the example module that I linked above you can also find how additional .py files can be reloaded dynamically:

Note, that reloading can be tricky. For example, if you reload the .py files in incorrect order (a.py uses b.py; but you reload a.py before b.py) then you may find that you need to reload multiple times to get everything updated.