# Organizing imports in python extensions that rely on other slicer extensions

**URL:** <https://discourse.slicer.org/t/organizing-imports-in-python-extensions-that-rely-on-other-slicer-extensions/24959>\
**Category:** Development\
**Tags:** python\
**Created:** [August 28, 2022, 7:47am UTC](https://discourse.slicer.org/t/organizing-imports-in-python-extensions-that-rely-on-other-slicer-extensions/24959 "2022-08-28T07:47:50Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![pll\_llq](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pll_llq/32/9408_2.png) [@pll\_llq](https://discourse.slicer.org/u/pll_llq)\
**Post date:** [August 28, 2022, 7:47am UTC](https://discourse.slicer.org/t/organizing-imports-in-python-extensions-that-rely-on-other-slicer-extensions/24959/1 "2022-08-28T07:47:50Z")

</div>

I have a file in my scripted python extension that interacts with another extension (SlicerIGT Watchdog specifically). I want to import `vtkMRMLWatchdogNode` in my python code to use it for type hints. When I add it to the import statements like

```python
from slicer import vtkMRMLLinearTransformNode, vtkMRMLWatchdogNode

```

the application launches and my module is loaded before SlicerIGT, thus before `vtkMRMLWatchdogNode` is available in the slicer namespace. This leads to an import error and a failure to load my python extension.

Is there a way to specify a dependency for a slicer python extension or any other way to get around the extension loading order which if I understand correctly is random?

---

<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:** [August 28, 2022, 10:59am UTC](https://discourse.slicer.org/t/organizing-imports-in-python-extensions-that-rely-on-other-slicer-extensions/24959/2 "2022-08-28T10:59:22Z")

</div>

MRML nodes are imported into the Slicer namespace automatically, you should not attempt to import them manually, as it is either unnecessary or premature.

You must not import any Python modules (other than built-in ones) in the body of the .py file, because order of module discovery is random. The application determines dependencies during module discovery and module loading is ordered based on dependencies that each module declares about itself.

Thr simplest is to observe the startup completed signal and perform actions that you want to do at startup but rely on existence of other modules in the callback function.

---

<div class="post-metadata">

**Author:** ![pll\_llq](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pll_llq/32/9408_2.png) [@pll\_llq](https://discourse.slicer.org/u/pll_llq)\
**Post date:** [August 28, 2022, 12:13pm UTC](https://discourse.slicer.org/t/organizing-imports-in-python-extensions-that-rely-on-other-slicer-extensions/24959/3 "2022-08-28T12:13:22Z")

</div>

Thanks. You are right, that import is unnecessary to have working code.

In my case the sole purpose of having that import is to enable certain functionality of my text editor (VSCode) that makes the development process faster and more pleasant in general. When I link the VSCode workspace to the `PythonSlicer` executable using the `python.defaultInterpreterPath` setting I get python related tooling (language server and linters) running from slicer.

The workaround is not worth the time in this case.

On the other note, can you please explain a bit what you mean by “must not import any Python modules (other than built-in ones) in the body of the .py file”. Are you referring to slicer python modules (like importing a logic class of another slicer extension) or generic python modules (numpy, torch, etc.)?

---

<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:** [August 28, 2022, 12:36pm UTC](https://discourse.slicer.org/t/organizing-imports-in-python-extensions-that-rely-on-other-slicer-extensions/24959/4 "2022-08-28T12:36:19Z")

</div>

You should not import numpy, torch, etc. either in the .py file body.

Pip-installed modules cannot be added there because the first time the module is discovered, the module is not available yet, so you cannot import it. If you added pip\_install in the .py file body then it would cause long delays at application startup (in case of torch, it could be several minutes - so users would assume the application is crashed).

Importing Python modules that are bundled with Slicer, such as numpy, used to be acceptable, but in Python-3.9 and Windows11 we ran into issues ([Slicer hung during startup](https://github.com/Slicer/Slicer/issues/5945) due to incorrect stdin/stdout usage in OpenBLAS), so now we don’t recommend importing anything.

> [@pll\_llq](#):
>
> In my case the sole purpose of having that import is to enable certain functionality of my text editor (VSCode) that makes the development process faster and more pleasant in general. When I link the VSCode workspace to the `PythonSlicer` executable using the `python.defaultInterpreterPath` setting I get python related tooling (language server and linters) running from slicer.

Time to time I test if I can get anything useful from this, but so far auto-completion, method documentation, syntax highlighting, linting, etc. have all mostly failed for Slicer scripted modules. Could you describe what IDE features work you?

---

<div class="post-metadata">

**Author:** ![pll\_llq](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pll_llq/32/9408_2.png) [@pll\_llq](https://discourse.slicer.org/u/pll_llq)\
**Post date:** [August 28, 2022, 12:52pm UTC](https://discourse.slicer.org/t/organizing-imports-in-python-extensions-that-rely-on-other-slicer-extensions/24959/5 "2022-08-28T12:52:41Z")

</div>

> [@lassoan](#):
>
> Could you describe what IDE features work you?

I can’t get docstrings for bundled slicer python modules if i’m not using a jupyter kernel.

I run some linting on save. If I link to `PythonSlicer` the linters don’t yell at me with false-positives like `qt` or `slicer` namespaces, thus checking only the code available in the workspace.

I have tried mypy, pylint, flake8 and pycodestyle and all of them worked to the extent of testing my code and not raising false-flags about the things that are expected from the slicer runtime.

---

<div class="post-metadata">

**Author:** ![pll\_llq](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.slicer.org/pll_llq/32/9408_2.png) [@pll\_llq](https://discourse.slicer.org/u/pll_llq)\
**Post date:** [August 28, 2022, 12:55pm UTC](https://discourse.slicer.org/t/organizing-imports-in-python-extensions-that-rely-on-other-slicer-extensions/24959/6 "2022-08-28T12:55:20Z")

</div>

> [@lassoan](#):
>
> Importing Python modules that are bundled with Slicer, such as numpy, used to be acceptable, but in Python-3.9 and Windows11 we ran into issues ([Slicer hung during startup](https://github.com/Slicer/Slicer/issues/5945) due to incorrect stdin/stdout usage in OpenBLAS), so now we don’t recommend importing anything.

This is very important information. Thanks a lot
