Never ask the user to copy-paste code. Instead, use Slicer web server that allows execution of Python code via a web API.
You can connect to a running instance of 3D Slicer by giving these instructions to the user: Go to Web Server module, enable "Slicer API exec" in Advanced section, and click "Start server" button.
Alternatively, find a free port (2016, 2017, 2018, ...) and start 3D Slicer with the Web Server "Slicer API exec" endpoint enabled:
# Windows (PowerShell)
# Prevent display of the memory leak popup that can block application exit
$env:DASHBOARD_TEST_FROM_CTEST = "1"
# First find the most recently installed Slicer automatically in the default install location.
$slicerExe = Get-ChildItem "$env:LOCALAPPDATA\slicer.org\3D Slicer*\Slicer.exe" -ErrorAction SilentlyContinue |
Sort-Object LastWriteTime -Descending | Select-Object -First 1
& $slicerExe.FullName --python-code "from WebServer import WebServerLogic; wsLogic = WebServerLogic(port=2016, enableExec=True); wsLogic.start()"# Linux / macOS
./Slicer --python-code "from WebServer import WebServerLogic; wsLogic = WebServerLogic(port=2016, enableExec=True); wsLogic.start()"Note that enableExec is off by default for security reasons and must be enabled explicitly.
After this, you can connect to Slicer and run Python commands as it is described here: https://slicer.readthedocs.io/en/latest/user_guide/modules/webserver.html#remote-control
Default endpoint: http://localhost:2016/slicer/exec (POST, plain-text Python body).
Return values go in __execResult dict → JSON response.
After modifying a module, always reload it in Slicer.
After you generated a module, load the module without restarting Slicer and do basic testing. Then ask the user to test.
You can find useful code snippets in the Slicer Script Repository: https://slicer.readthedocs.io/en/latest/developer_guide/script_repository.html
curl -s -X POST http://localhost:2016/slicer/exec --data-binary "
import qt
modulePath = r'C:\path\to\MyModule\MyModule.py' # absolute path to the .py file
searchPath = r'C:\path\to\MyModule' # directory that contains it
moduleName = 'MyModule' # filename without .py extension
factory = slicer.app.moduleManager().factoryManager()
# Step 1 – Register the module file
factory.registerModule(qt.QFileInfo(modulePath))
# Step 2 – Persist the search path so the module loads automatically after restart
settings = slicer.app.revisionUserSettings()
rawSearchPaths = list(settings.value('Modules/AdditionalPaths') or [])
if searchPath not in rawSearchPaths:
rawSearchPaths.append(searchPath)
settings.setValue('Modules/AdditionalPaths',
slicer.app.toSlicerHomeRelativePaths(rawSearchPaths))
# Step 3 – Instantiate and load
factory.loadModules([moduleName])
# Step 4 – Switch to the module
slicer.util.selectModule(moduleName)
__execResult = {'registered': factory.isRegistered(moduleName)}
"This is the same function the "Reload" button in Slicer's module panel calls (ScriptedLoadableModuleWidget.onReload):
curl -s -X POST http://localhost:2016/slicer/exec --data-binary "
slicer.util.reloadScriptedModule('LungVolume')
__execResult = {'reloaded': True}
"