Run a python script from Slicer

I want to run a custom python script from slicer in a custom virtual environment.

I tried:

  • slicer.util.launchConsoleProcess(), as suggested here, but I couldn’t figure out how to specify my custom venv
  • I tried using subprocess.call(cmd, shell=True, executable='/bin/bash'), where cmd = "source path/to/venv/bin/activate; python3 path/to/script.py (I tried this with . instead of source or without source but nothing worked)

I also tried a somewhat convoluted way that was the closest to working: subprocess.run(command_line, env=slicer.util.startupEnvironment()), where command_line=["path/to/venv/bin/python3.7", "path/to/intermediate/script.py"] and the intermediate python file contains an os.system call with the venv and ‘real’ script specified

  • I wrote that it partially worked because I get a return code of 0, and the loading circle in slicer appears for a moment - so I’m guessing the ‘real’ script started but then closed after a moment
    (the script I want to run is a script that continuously sends data to Slicer, where my extension then uses this data to update markups)

It seemed to me like I tried all the options that If found here on Discourse, but maybe I missed something.

I would expect that launchConsoleProcess would work if you launch a wrapper bash script (that activates the virtual environment and launches your Python script). Maybe first start with a very simple script (e.g., that prints a short message or creates a new file).

Is there a particular reason you cannot run your script in Slicer’s virtual Python environment (using PythonSlicer executable)?

I just tried using a bash script but I also couldn’t make it work.

That’s my script (which I can execute on my mac) - the python file creates a dummy directory:

#! /usr/bin/env python
source /Users/fryderykkogl/Documents/university/master/thesis/code.nosync/venvs.nosync/mpipe/bin/activate
python3 /Users/fryderykkogl/Documents/university/master/thesis/code.nosync/x-nav/x.py


I run it with
slicer.util.launchConsoleProcess(["/Users/fryderykkogl/Documents/university/master/thesis/code.nosync/x-nav/wrapper.sh"])

I first got a permission error which I fixed with chmod but now I get this error which I cannot get rid of:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/Applications/Slicer_debug.app/Contents/bin/Python/slicer/util.py", line 3384, in launchConsoleProcess
    proc = subprocess.Popen(args, env=startupEnv, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, cwd=cwd)
  File "/Applications/Slicer_debug.app/Contents/lib/Python/lib/python3.9/subprocess.py", line 951, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/Applications/Slicer_debug.app/Contents/lib/Python/lib/python3.9/subprocess.py", line 1821, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 8] Exec format error: '/Users/fryderykkogl/Documents/university/master/thesis/code.nosync/x-nav/wrapper.sh'


I don’t think there is a reason, but I also can’t figure out how to use PythonSlicer from within Slicer. I can use PythonSlicer from my terminal, but I run into the same problems as with my venv when I do it in Slicer

A note on ‘the big picture’ - I want to have a button in my custom extension, which when pressed, executes this custom script

You need to add /bin/bash as the first element of the list being passed to launchConsoleProcess.

That helped, thanks!!

However, my script now crashes at this line of code:
cap = cv2.VideoCapture(0)

(again, it crashes only when I try to execute it through Slicer - it runs fine when executed through my terminal)

I accessed the results of p = launchConsoleProcess() with p.communicate() and this was the error:

OpenCV: not authorized to capture video (status 0), requesting...

Also, Python crashes and I get a report which, amongst other things, says:

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an com.apple.security.device.camera key with a string value explaining to the user how the app uses this data.

When I try to run cap = cv2.VideoCapture(0) in the Slicer Python console I get a similar error:

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.

I can’t figure out how to add this information to the Info.plist file

I added those two lines to the Info.plist file that I found in /Applications/Slicer.app/Contents/Info.plist

<key>com.apple.security.device.camera</key>
<string>used_to_track_your_hand</string>
<key>NSCameraUsageDescription</key>
<string>also_used_to_track_your_hand</string>

Now it seems that the code runs further (it doesn’t crash at cap = cv2.VideoCapture(0)), but capcap.isOpened() returns False and the it I get such a message:

'OpenCV: not authorized to capture video (status 0), requesting...\nOpenCV: camera failed to properly initialize!

Those sound like permission issues with opencv and macOS at this point. Perhaps just run Slicer as root with sudo.

That unfortunately didn’t change anything.

I also tried adding sudo as an argument before /bin/bash/ (and disabled the need for a password when using sudo), but this also didn’t change anything