'cv2' python binding not working with 'opencv-python' part

Hello, I am fairly new and crafting a snap which requires opencv and in the scripts which use it it is imported with the binding “cv2” however I am getting a

ModuleNotFoundError: No module named 'cv2'

error even though I have a part which builds consisting of the following:

  # Opencv
  opencv:
    plugin: python
    python-packages:
      - opencv-python
    prime:
      - usr/lib/**/

am I including this incorrectly? FWIW here are the rest of my relevant parts:

  # Numpy
  numpy:
    plugin: python
    python-packages: 
      - numpy

  # Open3D pip library
  open3d:
    plugin: python
    python-packages:
      - open3d
    prime:
      - usr/lib/**/

I am not completely sure if my use of “prime” is correct or if there is a better way for me to install these parts but it does seem to satisfy all the lib library warnings. Is there a simple way to make sure snapcraft is aware of this binding?

It’s probably a case of PYTHONPATH not being set to include the correct paths.

Can you do

snap run --shell your-snap
python3 -c "import sys; import pprint; pprint.pprint(sys.path)"

?

Yes this runs fine (as long as I add the <.command> as I don’t have one that matches my snap name). It returns this:

snap run --shell open3d.record
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

mason@mason-XPS:/home/mason/mysnaps/open3D$ python3 -c "import sys; import pprint; pprint.pprint(sys.path)"
['',
 '/snap/open3d/x10/usr/lib/python36.zip',
 '/snap/open3d/x10/usr/lib/python3.6',
 '/snap/open3d/x10/usr/lib/python3.6/lib-dynload',
 '/snap/open3d/x10/usr/lib/python3/dist-packages',
 '/snap/open3d/x10/lib/python3.6/site-packages']

any ideas?

Drop the prime directive, or add lib/python3.6 to it.

Thank you for the suggestion, when I remove the prime I no longer get the modulenotfound error and instead get:

  File "/snap/open3d/x11/lib/python3.6/site-packages/cv2/__init__.py", line 5, in <module>
    from .cv2 import *
ImportError: libSM.so.6: cannot open shared object file: No such file or directory

additionally all the lib warnings return during the snapcraft step.

This part is missing libraries that cannot be satisfied with any available stage-packages known to snapcraft:
- libICE.so.6
- libSM.so.6
- libX11.so.6
- libXext.so.6
- libXrender.so.1

I tried adding -lib/python3.6 to the prime list which did not seem to have any effect, I also tried it as just - usr/lib/**/python3.6 which snapcraft is happy with but still has the modulenotfound error. Is there a better way to satisfy these libX requirements than my use of prime? I’m a bit unclear on if the prime files are coming from my development machine or the vm but my dev is 20.04/3.8 and my snap is core18/3.6.

@lucyllewy @ppd
I am working on dropping the prime and using a dependency install bash script that is in another part (dump) but can’t seem to get the override-build to find the script this is my latest attempt, I have tried a lot of different paths and environment variables but i’m definitely missing something. It is possible to have a part use another part right?

grade: devel # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

parts:
  # Open3D Directory
  open3d-directory:
    plugin: dump
    source: https://github.com/intel-isl/Open3D.git
    #source-subdir: examples/Python/ReconstructionSystem/sensors

  # open3d ubuntu dependencies
  ubuntu-deps:
    plugin: nil
    override-build: /parts/open3d-directory/util/scripts/install-deps-ubuntu.sh

  # numpy
  numpy:
    plugin: python
    python-packages: 
      - numpy

  # Opencv
  opencv:
    plugin: python
    python-packages:
      - opencv-python
    #prime:
    #  - usr/lib/**/python3.6

  #pyrealsense2 pip library
  pyrealsense2:
      plugin: python
      python-version: python3
      python-packages:
        - pyrealsense2
      stage-packages: 
        - libusb-1.0-0

  # Open3D pip library
  open3d:
    plugin: python
    python-packages:
      - open3d
    #prime:
    #  - usr/lib/**/

apps:
  record:
    command: python3 $SNAP/examples/Python/ReconstructionSystem/sensors/realsense_recorder.py --record_imgs

To use the built assets from a different part you need to add an after: clause:

parts:
  part-a:
    plugin: dump
    source: .
  part-depends-on-a:
    after: [part-a]
    plugin: nil

Note that you should copy the files you depend on from the part to $SNAPCRAFT_PART_INSTALL and then use them from $SNAPCRAFT_STAGE. You can omit them from the final snap with a prime: clause:

parts:
  contains-setup-sh:
    plugin: dump
    source: .
    prime:
      - '-setup.sh'
  uses-setup-sh:
    after: [contains-setup-sh]
    plugin: nil
    override-build: |
      $SNAPCRAFT_STAGE/setup.sh