eccodes-python icon indicating copy to clipboard operation
eccodes-python copied to clipboard

Missing binary on Linux install via pypi in newer versions (2.39.0 - 2.40.0)

Open bnubald opened this issue 1 year ago • 10 comments

What happened?

Installing newer versions of eccodes not finding/including binary.

When attempting to use eccodes (latest -> v2.40.0), I was getting an error, and using self check, showed me the included error. In trying to find out if it was a system issue, I tried installing versions since the binary was included, and found the earlier versions working, here is a list:

  • 2.37.0 (working)
  • 2.38.0 (working)
  • 2.38.1 (working)
  • 2.38.3 (working)
  • 2.39.0 (not working)
  • 2.39.1 (not working)
  • 2.39.2 (not working)
  • 2.40.0 (not working)

This is the output when working, and I'm able to use these versions to read data without issue:

❯ export ECCODES_PYTHON_TRACE_LIB_SEARCH=1
❯ pip install eccodes==2.37
❯ python -m eccodes selfcheck
eccodes lib search: trying to find binary wheel
eccodes lib search: looking in /data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes.libs
eccodes lib search: returning wheel library from /data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes.libs/libeccodes-aadb7c6a.so
eccodes lib search: versions: {'eccodes': '2.37.0'}
Found: ecCodes v2.37.0.
Library: /data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes.libs/libeccodes-aadb7c6a.so
Definitions: /MEMFS/definitions
Samples: /MEMFS/samples
Your system is ready.

What are the steps to reproduce the bug?

❯ pip install eccodes
❯ export ECCODES_PYTHON_TRACE_LIB_SEARCH=1
❯ python -m eccodes selfcheck

Version

v2.39.0, v2.39.1, v2.39.2, v2.40.0

Platform (OS and architecture)

CentOS Linux 7 (Core), and on Rocky Linux 9.5 (Blue Onyx)

Relevant log output

eccodes lib search: trying to find binary wheel
eccodes lib search: looking in /data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes.libs
eccodes lib search: looking in /data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes/.dylibs
eccodes lib search: looking in /data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes
eccodes lib search: did not find library from wheel; try to find as separate lib
Traceback (most recent call last):
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/runpy.py", line 188, in _run_module_as_main
    mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/runpy.py", line 147, in _get_module_details
    return _get_module_details(pkg_main_name, error)
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/runpy.py", line 111, in _get_module_details
    __import__(pkg_name)
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes/__init__.py", line 13, in <module>
    from .eccodes import *  # noqa
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes/eccodes.py", line 12, in <module>
    from gribapi import (
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/gribapi/__init__.py", line 13, in <module>
    from .gribapi import *  # noqa
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/gribapi/gribapi.py", line 34, in <module>
    from gribapi.errors import GribInternalError
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/gribapi/errors.py", line 16, in <module>
    from .bindings import ENC, ffi, lib
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/gribapi/bindings.py", line 102, in <module>
    library_path = find_binary_libs("eccodes")
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/gribapi/bindings.py", line 95, in find_binary_libs
    import findlibs
  File "/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/findlibs/__init__.py", line 78, in <module>
    lib_name: str, pkg_name: str, preload_deps: bool | None = None
TypeError: unsupported operand type(s) for |: 'type' and 'NoneType'

Relevant diff?: https://github.com/ecmwf/eccodes-python/compare/2.38.3...2.39.0

Accompanying data

https://github.com/pydata/xarray-data/blob/d90be9863e8f8bbba980c1070b70628a18ab8d48/era5-2mt-2019-03-uk.grib

Organisation

British Antarctic Survey

bnubald avatar Feb 17 '25 12:02 bnubald

The following eccodes.libs directory that was created when installing 2.37-2.38.3 is missing with 2.39.0+:

/data/hpcdata/users/username/miniconda3/envs/ffmpeg_del/lib/python3.9/site-packages/eccodes.libs

bnubald avatar Feb 17 '25 12:02 bnubald

Hi @bnubald, I suspect the reason you are seeing this change of behaviour is that from version 2.39.0 of ecCodes, we changed the version of the Docker image we use to build the wheels from manylinux_2_17_x86_64 to manylinux_2_28_x86_64. This was because we found that GihUb Actions could no longer run on the older version. This means that the binary wheel will not work on such old OS versions as Centos 7. I think that one (hopefully) easy solution for you, since you seem to be in a conda environment, is to 'conda install eccodes -c conda-forge' in order to get the binary installed.

iainrussell avatar Feb 20 '25 15:02 iainrussell

Hi - I'm seeing this same issue installing eccodes with pip in a docker image using python:3.11-slim and python:3.10-slim. I had 2.40.0 pinned locally in a venv (macos) which includes the binary, but I can't find a version that installs the binary in my container. I tried 2.37.0, 2.38.0, 2.38.3, and 2.40.0.

root@ffd3859b124b:~#  ECCODES_PYTHON_TRACE_LIB_SEARCH=1 python -m cfgrib selfcheck
eccodes lib search: trying to find binary wheel
eccodes lib search: looking in /app/.venv/lib/python3.11/site-packages/eccodes.libs
eccodes lib search: looking in /app/.venv/lib/python3.11/site-packages/eccodes/.dylibs
eccodes lib search: looking in /app/.venv/lib/python3.11/site-packages/eccodes
eccodes lib search: did not find library from wheel; try to find as separate lib
eccodes lib search: findlibs returned None
Traceback (most recent call last):
  File "<frozen runpy>", line 189, in _run_module_as_main
  File "<frozen runpy>", line 148, in _get_module_details
  File "<frozen runpy>", line 112, in _get_module_details
  File "/app/.venv/lib/python3.11/site-packages/cfgrib/__init__.py", line 20, in <module>
    from .cfmessage import COMPUTED_KEYS
  File "/app/.venv/lib/python3.11/site-packages/cfgrib/cfmessage.py", line 29, in <module>
    from . import abc, messages
  File "/app/.venv/lib/python3.11/site-packages/cfgrib/messages.py", line 28, in <module>
    import eccodes  # type: ignore
    ^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/eccodes/__init__.py", line 13, in <module>
    from .eccodes import *  # noqa
    ^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/eccodes/eccodes.py", line 12, in <module>
    from gribapi import (
  File "/app/.venv/lib/python3.11/site-packages/gribapi/__init__.py", line 13, in <module>
    from .gribapi import *  # noqa
    ^^^^^^^^^^^^^^^^^^^^^^
  File "/app/.venv/lib/python3.11/site-packages/gribapi/gribapi.py", line 34, in <module>
    from gribapi.errors import GribInternalError
  File "/app/.venv/lib/python3.11/site-packages/gribapi/errors.py", line 16, in <module>
    from .bindings import ENC, ffi, lib
  File "/app/.venv/lib/python3.11/site-packages/gribapi/bindings.py", line 106, in <module>
    raise RuntimeError("Cannot find the ecCodes library")
RuntimeError: Cannot find the ecCodes library

any other solutions besides trying to install it manually?

dschneider-wxs avatar Feb 21 '25 19:02 dschneider-wxs

related https://github.com/ecmwf/eccodes-python/issues/104

dschneider-wxs avatar Feb 21 '25 19:02 dschneider-wxs

Hi @bnubald, I suspect the reason you are seeing this change of behaviour is that from version 2.39.0 of ecCodes, we changed the version of the Docker image we use to build the wheels from manylinux_2_17_x86_64 to manylinux_2_28_x86_64. This was because we found that GihUb Actions could no longer run on the older version. This means that the binary wheel will not work on such old OS versions as Centos 7. I think that one (hopefully) easy solution for you, since you seem to be in a conda environment, is to 'conda install eccodes -c conda-forge' in order to get the binary installed.

Thanks @iainrussell, can confirm your suspicion, a direct install via pypi on Rocky Linux 9.5 (Blue Onyx) is working with the newer versions.

I was attempting to migrate away from needing conda and trying to strip such dependencies, I will probably set version specifier for now since we're in the process of migrating to Rocky 9.

Thanks again! Happy to close if @dschneider-wxs's issue is covered in #104

bnubald avatar Mar 04 '25 10:03 bnubald

I confirm that the following is not working as expected: docker run -it --rm python:3.13 bash -c "pip install eccodes; python -m eccodes selfcheck"

Collecting eccodes
  Downloading eccodes-2.41.0-py3-none-any.whl.metadata (14 kB)
Collecting numpy (from eccodes)
  Downloading numpy-2.3.0-cp313-cp313-manylinux_2_28_aarch64.whl.metadata (62 kB)
Collecting attrs (from eccodes)
  Downloading attrs-25.3.0-py3-none-any.whl.metadata (10 kB)
Collecting cffi (from eccodes)
  Downloading cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.metadata (1.5 kB)
Collecting findlibs (from eccodes)
  Downloading findlibs-0.1.1-py3-none-any.whl.metadata (3.6 kB)
Collecting pycparser (from cffi->eccodes)
  Downloading pycparser-2.22-py3-none-any.whl.metadata (943 bytes)
Downloading eccodes-2.41.0-py3-none-any.whl (44 kB)
Downloading attrs-25.3.0-py3-none-any.whl (63 kB)
Downloading cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (478 kB)
Downloading findlibs-0.1.1-py3-none-any.whl (10 kB)
Downloading numpy-2.3.0-cp313-cp313-manylinux_2_28_aarch64.whl (14.3 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 14.3/14.3 MB 34.4 MB/s eta 0:00:00
Downloading pycparser-2.22-py3-none-any.whl (117 kB)
Installing collected packages: findlibs, pycparser, numpy, attrs, cffi, eccodes
Successfully installed attrs-25.3.0 cffi-1.17.1 eccodes-2.41.0 findlibs-0.1.1 numpy-2.3.0 pycparser-2.22
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
Traceback (most recent call last):
  File "<frozen runpy>", line 189, in _run_module_as_main
  File "<frozen runpy>", line 148, in _get_module_details
  File "<frozen runpy>", line 112, in _get_module_details
  File "/usr/local/lib/python3.13/site-packages/eccodes/__init__.py", line 13, in <module>
    from .eccodes import *  # noqa
    ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/eccodes/eccodes.py", line 12, in <module>
    from gribapi import (
    ...<8 lines>...
    )
  File "/usr/local/lib/python3.13/site-packages/gribapi/__init__.py", line 13, in <module>
    from .gribapi import *  # noqa
    ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.13/site-packages/gribapi/gribapi.py", line 34, in <module>
    from gribapi.errors import GribInternalError
  File "/usr/local/lib/python3.13/site-packages/gribapi/errors.py", line 16, in <module>
    from .bindings import ENC, ffi, lib
  File "/usr/local/lib/python3.13/site-packages/gribapi/bindings.py", line 105, in <module>
    raise RuntimeError("Cannot find the ecCodes library")
RuntimeError: Cannot find the ecCodes library

Also tested with python:3.12 and python:3.11 and against multiple eccodes version 2.37 -> 2.41

EDIT: The gribapi/bindings.py will search into the current directory where eccodes.py is. And I actually do not have any .so library inside.

>> root@38991e775135: /usr/local/lib/python3.13/site-packages# ls eccodes
__init__.py  __main__.py  __pycache__  eccodes.py  highlevel

folkvir avatar Jun 11 '25 16:06 folkvir

Yes I reached the same conclusion:

  • on most architectures you will see _eccodes.cc and _eccodes.cpython-313-x86_64-linux-gnu.so or _eccodes.cpython-313-darwin.so
  • on Linux/aarch64 seems not supported so falls back to a version which seems to not be able to work with the .so.0 files offered by the libeccodes0:arm64 deb file

xoolive avatar Jun 11 '25 22:06 xoolive

Do you have any workaround with aarch64? I tried to install the libeccodes0 debian package (for version 2.41.0-1) which provide the libeccodes.so.0 but still does not work. I tried to copy the .so.0 files into the eccodes site-packages and rename it into .so to satisfy the gribapi/bindings.py but it is still not working at all.

  File "/usr/src/app/explore/.venv/lib/python3.13/site-packages/gribapi/bindings.py", line 81, in find_binary_libs
    from eccodes._eccodes import versions as _versions
ModuleNotFoundError: No module named 'eccodes._eccodes'

folkvir avatar Jun 12 '25 07:06 folkvir

No, not yet, I finished working on it late yesterday...

I think the best way I have in mind is to compile a version of eccodes for aarch64 on a Docker image and use that wheel rather than the default one on pypi. Ideally that wheel should be on PyPi already...

xoolive avatar Jun 12 '25 08:06 xoolive

I tried your suggestion by building everything myself and it worked 👍 What I did:

FROM python:3.13.4-bookworm
RUN apt update
ENV ECCODES_VERSION=2.41.0
# Fetch eccodes sources and build it
RUN mkdir -p /custom/eccodes \
    && cd /custom/eccodes \
    && wget https://confluence.ecmwf.int/download/attachments/45757960/eccodes-$ECCODES_VERSION-Source.tar.gz?api=v2 -O eccodes-$ECCODES_VERSION-Source.tar.gz \
    && tar -xzf eccodes-$ECCODES_VERSION-Source.tar.gz
RUN apt install -y cmake
RUN mkdir -p /custom/eccodes/build \
    && cd /custom/eccodes/build \
    && cmake ../eccodes-$ECCODES_VERSION-Source -DCMAKE_INSTALL_PREFIX=/custom/eccodes/build -DENABLE_FORTRAN=0 \
    && make \
    && make install
RUN cp -a /custom/eccodes/build/bin/. /usr/bin/ \
    && cp -a /custom/eccodes/build/lib/. /usr/lib/ \
    && cp -a /custom/eccodes/build/include/. /usr/include/ \
    && cp -a /custom/eccodes/build/share/. /usr/share
# Fetch eccodes bindings and build it
RUN mkdir -p /custom/eccodes-python \
    && git clone https://github.com/ecmwf/eccodes-python /custom/eccodes-python \
    && cd /custom/eccodes-python \
    && pip install setuptools \
    && pip install -e . \
    && python builder.py
RUN python -m eccodes selfcheck

<......>
# Tells the .venv to go searching for system libraries
RUN echo "/usr/local/lib/python3.13/site-packages/" > .venv/lib/python3.13/site-packages/systemlibs.pth
root@5fbccfaac663:/usr/src/app/explore# uv run python -m eccodes selfcheck
Found: ecCodes v2.41.0.
Library: /lib/libeccodes.so
Definitions: /custom/eccodes/build/share/eccodes/definitions
Samples: /custom/eccodes/build/share/eccodes/samples
Your system is ready.

folkvir avatar Jun 12 '25 10:06 folkvir