Skip to content

Package conflict between opencv-python and opencv-python-headless #467

Closed
@Erotemic

Description

@Erotemic

Preface: This is somewhat of a weird issue because I can't manage reproduce it with a MWE (perhaps someone here will be able to shed light on why).

I have a library: kwimage that depends on the cv2 module, and there are two main ways of obtaining this with pip. Either opencv-python or opencv-python-headless. Currently the install_requires simply specified "opencv-python".

The issue is that opencv-python contains libraries that can conflict with pyqt5, which I often see when I'm using matplotlib. Using opencv-python-headless works around this issue.

The problem is that pip has gotten too smart for its own good. If I uninstall opencv-python and install opencv-python-headless, it throws some requirements not satisfied error, but I can't figure out how to reproduce that reliably (in that I can't set up another package where it lists some package as a dependency and then remove it to reproduce the error). However, when it does happen it looks like this:

ERROR ex = DistributionNotFound(Requirement.parse('opencv-python'), {'kwimage'})
Traceback (most recent call last):
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/bin/kwcoco", line 33, in <module>
    sys.exit(load_entry_point('kwcoco', 'console_scripts', 'kwcoco')())
  File "/home/joncrall/code/kwcoco/kwcoco/cli/__main__.py", line 112, in main
    ret = main(cmdline=False, **kw)
  File "/home/joncrall/code/kwcoco/kwcoco/cli/coco_validate.py", line 81, in main
    result = dset.validate(**config_)
  File "/home/joncrall/code/kwcoco/kwcoco/coco_dataset.py", line 2670, in validate
    from kwcoco.coco_schema import COCO_SCHEMA
  File "/home/joncrall/code/kwcoco/kwcoco/coco_schema.py", line 42, in <module>
    from kwcoco.util.jsonschema_elements import SchemaElements
  File "/home/joncrall/code/kwcoco/kwcoco/util/__init__.py", line 6, in <module>
    from kwcoco.util import util_sklearn
  File "/home/joncrall/code/kwcoco/kwcoco/util/util_sklearn.py", line 6, in <module>
    from sklearn.utils.validation import check_array
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/sklearn/__init__.py", line 82, in <module>
    from .base import clone
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/sklearn/base.py", line 17, in <module>
    from .utils import _IS_32BIT
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/sklearn/utils/__init__.py", line 23, in <module>
    from .class_weight import compute_class_weight, compute_sample_weight
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/sklearn/utils/class_weight.py", line 7, in <module>
    from .validation import _deprecate_positional_args
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/sklearn/utils/validation.py", line 26, in <module>
    from .fixes import _object_dtype_isnan, parse_version
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/sklearn/utils/fixes.py", line 28, in <module>
    from pkg_resources import parse_version  # type: ignore
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/pkg_resources/__init__.py", line 3262, in <module>
    def _initialize_master_working_set():
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/pkg_resources/__init__.py", line 3245, in _call_aside
    f(*args, **kwargs)
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/pkg_resources/__init__.py", line 3274, in _initialize_master_working_set
    working_set = WorkingSet._build_master()
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/pkg_resources/__init__.py", line 584, in _build_master
    ws.require(__requires__)
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/pkg_resources/__init__.py", line 901, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/home/joncrall/.pyenv/versions/3.8.5/envs/py385/lib/python3.8/site-packages/pkg_resources/__init__.py", line 787, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'opencv-python' distribution was not found and is required by kwimage

I'm currently going to work around this by making both opencv-python and opencv-python-headless optional installs in the install_extras section with different tags. This will solve 80% of the issue, but I think a modification to how these opencv wheels are produced might 100% solve the issue.

What I'm wondering is if it is possible for there to be an opencv-python-base package, which is effectively the headless code and then a plugin package opencv-python-graphics could be installed on top of that to only add the qt-libs? Thus the opencv-python package could maintain backwards compatibility by simply being a meta package that requires opencv-python-base and opencv-python-graphics.

I'm not sure if this is easy / possible to do, because perhaps the "non-headless" library has some compile time difference that can't be augmented at runtime.

If anyone can shed more light on the pkg_resources issue or comment on the feasibility of the "graphics-libs-as-a-plugin-module" idea, that would be appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions