Developing Slicer modules in Visual Studio / Visual Studio Code?

I’ve executed slicer.util.pip_install("pylint rope autopep8") in Slicer’s Python console and set python.pythonpath in VS Code to c:\Users\andra\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-11\bin\PythonSlicer.exe. After this I restarted VS Code, opened a file, and entered:

import vtk
a=vtk.vtkImageData()
a.Get

At this point, I would expect pressing Ctrl-space would bring up Get… methods of vtkImageData, but only a few method names show up (that are used in the file).

@Alex_Vergara does auto-complete or documentation work for you for VTK and Slicer classes? Do you use Jedi as IntelliSense engine (python.jediEnabled)? Seeing a few screenshots and/or videos about what you have working in VS Code would be great.

Here you can see VSCode recognizes the python inside Slicer

My settings.json inside project .vscode folder
image

the vscode general settings.json
image

You need to add the extrapaths to your python, I know I have them in the wrong place, but I am being lazy to move them. anyways, you need the python.autocomplete.extrapaths added to your settings too.
As you can see ctrl+space already gives me all necesary hints
image

This is for Linux, right? What “settings.json” and “extrapaths” should I have to change in Windows?
Thanks

On Windows, I’ve tried to add the extra paths but nothing changed. It still does not recognize anything.

Ok, I have fixed my settings to be module specific, now they are as
image

and this worked for me in mac, linux and windows

This sounds very promising! Can you copy here your settings for Windows? (and if possible, not as screenshot, but as text) Thank you.

I was able to get auto completion within Visual Studio Code on Windows following these settings:

“C:\Users\JamesButler\AppData\Roaming\Code\User\settings.json”

{
    "python.pythonPath": "C:\\Program Files\\Slicer 4.11.0-2019-12-06\\bin\\SlicerPython",
    "python.autoComplete.extraPaths": [
        "C:\\Program Files\\Slicer 4.11.0-2019-12-06\\",
        "C:\\Program Files\\Slicer 4.11.0-2019-12-06\\lib\\Python",
        "C:\\Program Files\\Slicer 4.11.0-2019-12-06\\lib\\QtPlugins",
        "C:\\Program Files\\Slicer 4.11.0-2019-12-06\\lib\\Slicer-4.11",
        "C:\\Program Files\\Slicer 4.11.0-2019-12-06\\bin",
    ],
}

autocomplete-vscode

2 Likes

Thanks! Do you have auto-complete for VTK or Slicer MRML classes, too?

It appears to only be working for these pure python modules like util with the settings that I used.

In the image below you can see some of the auto-complete for the slicer module (there are more if I scrolled down in the pop-up). There is no mrmlScene so unfortunately no slicer.mrmlScene.XX auto-complete. Also missing items for vtk. Maybe a setting can be changed, but I was just using the reference from @Alex_Vergara.
autocomplete-vscode2 autocomplete-vscode3

1 Like

Ok. Now, I have libraries recognition and it´s really cool. I still have problems with pylint rope and autopep8. Python console throw this error.

image

Thank you all.

The package name is slicer.util (and not slicer.utils).

In windows project settings does not work, you need to edit global settings for vscode for it to work. Here it is my settings.json in C:\Users\alexv\AppData\Roaming\Code\User\settings.json

{
    "python.pythonPath": "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\bin\\PythonSlicer.exe",
    "python.linting.pylintPath": "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\lib\\Python\\Scripts\\pylint.exe",
    "python.formatting.autopep8Path": "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\lib\\Python\\Scripts\\autopep8.exe",
    "python.autoComplete.extraPaths": [
        "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\",
        "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\bin\\",
        "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\lib\\Python\\",
        "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\lib\\QtPlugins\\",
        "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\lib\\Slicer-4.11\\",
        "C:\\Users\\alexv\\AppData\\Local\\NA-MIC\\Slicer 4.11.0-2019-11-05\\lib\\Python\\Scripts\\",
    ],
    "python.linting.enabled": true,
    "git.autofetch": true
}

And you don’t need any python installed in your system, just python extension in vscode.
image

Thank you. With the above settings I get auto-complete for native python classes (slicer.util, etc). This is good! Even VTK and other C++ wrapped libraries show up and classes are listed, but unfortunately method names and method documentation does not show up and auto-complete does not work either.

Maybe VTK’s Python wrapping could be made more friendly to IDEs, but with this we’ll have to wait until we upgrade to latest VTK master early next year.

I think that is because vtk and ctk are located in a very different folder

E15TY:dosimetry4d alexvergaragil$ ls /Applications/Slicer.app/Contents/bin/Python/
SlicerWizard            ctk                     mrml.py                 qt                      slicer                  vtkAddon.py             vtkSegmentationCore.py  vtkmodules
__pycache__             freesurfer.py           mrmlDisplayableManager  sitkUtils.py            vtk.py                  vtkITK.py               vtkTeem.py

So adding it to autocomplete paths
image
and
image

My configuration file is now

{
    "python.pythonPath": "/Applications/Slicer.app/Contents/bin/SlicerPython",
    "python.autoComplete.extraPaths": [
        "/Applications/Slicer.app/Contents",
        "/Applications/Slicer.app/Contents/lib/Python",
        "/Applications/Slicer.app/Contents/lib/QtPlugins",
        "/Applications/Slicer.app/Contents/lib/Slicer-4.11",
        "/Applications/Slicer.app/Contents/bin/",
        "/Applications/Slicer.app/Contents/bin/Python/",
        "/Applications/Slicer.app/Contents/bin/Python/vtkmodules"
    ],
    "python.linting.pylintPath": "/Applications/Slicer.app/Contents/lib/Python/bin/pylint",
    "python.formatting.autopep8Path": "/Applications/Slicer.app/Contents/lib/Python/bin/autopep8",
    "python.linting.enabled": true,
    "git.autofetch": true
}

I still have problems trying to fix Visual Studio Code configuration for Windows.

Proposed steps:

1º - Open Slicer Python Interector and install pylint, rope and autopep8:
slicer.util.pip_install(“pylint rope autopep8”)

2º - Open Visual Studio Code settings.json (located in C:\Users"user"\AppData\Roaming\Code\User)

3º - Items to add:

{
“python.pythonpath”: “C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\bin\SlicerPython.exe”,
“python.linting.pylintPath”: “C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Lib\site-packages\pylint\”,
“python.formatting.autopep8Path”: “C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Scripts\autopep8.exe”,
“python.autoComplete.extraPaths”: [
“C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\”,
“C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\”,
“C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\QtPlugins\”,
“C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Slicer-4.11\”,
“C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\bin\”,
“C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Lib\site-packages\”,
“C:\Users\user\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Scripts\”,
],
“python.linting.enabled”: true,
“git.autofetch”: true
}

Now I have no errors in VSC but autocomplete is not working.

I´ve tried @Alex_Vergara code but VSCode throws error in import libraries and others…

I have no clear idea of which are the right directies of Slicer we need to add to extraPaths nor there is any difference between pythonpath “SlicerPython” or “PythonSlicer.exe”.

If this issue is fixed, muybe it should be added to documentation …

Thanks to all

There is no difference. Originally, we added SlicerPython, but then we realized then PyCharm only accept interpreter name if it starts with “python”. We kept “SlicerPython” for backward compatibility but probably we’ll remove it at some point.

Note that autocomplete, breakpoints, step-by-step debugging, stack walking, running local commands, inspecting and modifying variables, etc. all already works perfectly if you attach Python debugger to a running Slicer and put a breakpoint into the method that you are editing. So, all that we are trying to achieve here would just offer some additional convenience.

I agree with you debugger features are better than python config in VS Code…

If anyone want just to fix VS Code in Windows as we have been talking about can follow these steps:

1º - Open Slicer Python Interector and install pylint, rope and autopep8:
slicer.util.pip_install(“pylint rope autopep8”)

2º - Open Visual Studio Code settings.json (located in C:\Users\“user”\AppData\Roaming\Code\User)

3º - Items to add:

{
“python.pythonPath”: “C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\bin\SlicerPython.exe”,
“python.linting.pylintPath”: “C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Lib\site-packages\pylint\”,
“python.formatting.autopep8Path”: “C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Scripts\autopep8.exe”,
“python.autoComplete.extraPaths”: [
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\QtPlugins\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Slicer-4.11\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Scripts\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Lib\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Lib\site-packages\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\lib\Python\Lib\site-packages\pylint\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\bin\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\bin\Python\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\bin\Lib\site-packages\”,
“C:\Users\“user”\AppData\Local\NA-MIC\Slicer 4.11.0-2019-12-02\bin\Lib\site-packages\vtkmodules\”,
],
“python.linting.enabled”: true,
“git.autofetch”: true
}

Thanks so much for your support…

1 Like

I’ve created a script that collects all the above paths from the current Slicer instance and updates Visual Studio Code settings file automatically:

import os
import json

# Make sure all required packages are installed
slicer.util.pip_install("pylint rope autopep8 jedi")

binPath = slicer.app.applicationDirPath()  # 'C:/Users/(username)/AppData/Local/NA-MIC/Slicer (version)/bin'
appPath = os.path.dirname(slicer.app.applicationDirPath())  # 'C:/Users/(username)/AppData/Local/NA-MIC/Slicer (version)'
pythonHomePath = os.getenv('PYTHONHOME')  # 'C:/Users/(username)/AppData/Local/NA-MIC/Slicer (version)/lib/Python'
vsCodeUserSettingsFilePath = os.path.join(os.getenv("APPDATA"),"Code/User/settings.json")

# Read VS code settings file
with open(vsCodeUserSettingsFilePath) as vsCodeUserSettingsFile:
    vsCodeUserSettings = json.load(vsCodeUserSettingsFile)

# Update settings

vsCodeUserSettings["python.pythonPath"] = os.path.normpath(os.path.join(binPath, "SlicerPython.exe"))

vsCodeUserSettings["python.linting.pylintPath"] = os.path.normpath(os.path.join(pythonHomePath, "Scripts/pylint.exe"))
vsCodeUserSettings["python.linting.enabled"] = True

vsCodeUserSettings["python.formatting.autopep8Path"] = os.path.normpath(os.path.join(pythonHomePath, "Scripts/autopep8.exe"))

vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(appPath))
vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(binPath))
vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(pythonHomePath))
vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(os.path.join(pythonHomePath, "Scripts")))
vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(os.path.join(pythonHomePath, "Lib")))
vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(os.path.join(pythonHomePath, "Lib/site-packages")))
vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(os.path.join(pythonHomePath, "Lib/site-packages/pylint")))
vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(os.path.join(binPath, "Lib/site-packages/vtkmodules")))
vsCodeUserSettings["python.autoComplete.extraPaths"].append(os.path.normpath(os.path.join(appPath, "lib/QtPlugins")))
# Remove duplicates
vsCodeUserSettings["python.autoComplete.extraPaths"] = list(set(vsCodeUserSettings["python.autoComplete.extraPaths"]))

# Write VS code settings file
with open(vsCodeUserSettingsFilePath, "w") as vsCodeUserSettingsFile:
    json.dump(vsCodeUserSettings, vsCodeUserSettingsFile, indent=4)

Unfortunately, it does not do much for me. For example, if I type:

import vtkSegmentationCore as sc
s = sc.vtkSegmentation()

then methods of object s do not show up. If anybody can make VTK, MRML, CTK, or Qt method name auto-complete work in VS Code then please let me know.

4 Likes

C++ Tips: Using the CMake Tool by Microsoft really helped as it also provides the option to add generated build files to intellisense automatically (also need to have the c++ extension by microsoft installed). I’ve also attached my tasks.json and launch.json that launches slicer with my loadable c++ extension by pressing F5.

I open vscode in the base directory of my extension
Make sure to change to your extensions name to launch correctly

launch.json

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "(Linux) Launch Extension",
      "type": "cppdbg",
      "request": "launch",
      "program": "${workspaceFolder}/build/SlicerWith<NAME OF EXTENSION>",
      "args": [
        "--attach-process"
      ],
      "preLaunchTask": "(Linux) build",
      "stopAtEntry": true,
      "cwd": "${workspaceFolder}",
      "launchCompleteCommand": "exec-run",
      "linux": {
        "MIMode": "gdb",
        "miDebuggerPath": "/usr/bin/gdb"
      },
      "symbolLoadInfo": {
        "loadAll": true,
        "exceptionList": ""
      },
      "environment": [],
      "externalConsole": true,
      "additionalSOLibSearchPath": "${workspaceFolder}/build/lib/Slicer-4.11/qt-loadable-modules;<PATH TO SLICER BUILD>/Slicer-build/lib/Slicer-4.11/qt-loadable-modules"
    }
  ]
}

tasks.json

{
  "tasks": [
    {
      "label": "(Linux) build",
      "type": "shell",
      "command": "cmake --build ${workspaceFolder}/build --config Debug --target all -- -j <NUMBER OF CORES> ../"
    }
  ],
  "version": "2.0.0"
}

Notes

  • Make sure to change all instances with angle brackets inside to match your computers settings.
  • I’m still trying to figure out how to debug cpp with vscode instead of having to use gdb. As of now, you will have to open gdb separately in a terminal after starting the above code (basically running your extension ./SlicerWith(Extension Name) --atach-process) to get your process id. Then in a new terminal:
gdb -p <process_id>
(gdb) # place breakpoints
(gdb) continue # to run

I have followed the conversation and have set up my settings.json as such:

“python.pythonPath”: “C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\bin\PythonSlicer.exe”,
“python.linting.pylintPath”: “C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\Python\Scripts\pylint.exe”,
“python.formatting.autopep8Path”: “C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\Python\Scripts\autopep8.exe”,
“python.autoComplete.extraPaths”: [
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\bin\”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\Python\”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\QtPlugins\”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\Slicer-5.4\”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\Python\Scripts\”,
],
“python.linting.enabled”: true,
“git.autofetch”: true,
“python.analysis.extraPaths”: [
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\bin\”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\Python\”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\QtPlugins\”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\Slicer-5.4\”,
“C:\Users\smoudour\AppData\Local\slicer.org\Slicer 5.4.0\lib\Python\Scripts\”
],
“editor.fontLigatures”: false

Problems are:

  1. it still doesn’t work. Do I need to instal slicer using conda for this to work?
  2. python.pythonPath, python.linting.pylinPath and some other keywords in vscode settings.json are labelled as “Unknown configuration setting”, so that’s why it probably does not work. Any help with this?