PolarBear10
PolarBear10

Reputation: 2305

django.core.exceptions.ImproperlyConfigured: Could not find the GDAL library - m1 mac

I am trying to create a Pyinstaller on m1 mac for my django app.

When I run ./build.sh which contains

source .env/bin/activate
pyinstaller backend/manage.py -F \
--name "test" \
--icon='icon.ico' \
--add-data "backend/*:package" \

I get the following error

144 WARNING: Failed to collect submodules for 'django.contrib.gis.utils' because 

importing 'django.contrib.gis.utils' raised: django.core.exceptions.ImproperlyConfigured: 

Could not find the GDAL library (tried "gdal", "GDAL", "gdal3.4.0", "gdal3.3.0", 

"gdal3.2.0", "gdal3.1.0", "gdal3.0.0", "gdal2.4.0", "gdal2.3.0", "gdal2.2.0"). Is GDAL 

installed? If it is, try setting GDAL_LIBRARY_PATH in your settings.

In my settings.py I have

GDAL_LIBRARY_PATH = "/opt/homebrew/Cellar/gdal/3.5.2/lib/libgdal.dylib"
GEOS_LIBRARY_PATH = "/opt/homebrew/Cellar/geos/3.11.0/libgeos_c.1.17.0.dylib"

Amd in terminal

/opt/homebrew/opt/geos/lib/libgeos_c.dylib: Mach-O 64-bit dynamically linked shared library arm64
/opt/homebrew/Cellar/gdal/3.5.2/lib/libgdal.dylib: Mach-O 64-bit dynamically linked shared library arm64

Upvotes: 1

Views: 2504

Answers (2)

Arjan
Arjan

Reputation: 23569

Setting Django's GDAL_LIBRARY_PATH and all as per Diki Bhuyan's answer indeed helps. Still some more details for whoever is going mad due to things working/failing randomly on Apple silicon:

  1. Homebrew-installed Python includes the Homebrew /opt/homebrew/lib directory when searching for libraries, so will also find Homebrew-installed GDAL:

    /opt/homebrew/bin/python3 -c 'import ctypes.util; print(ctypes.util.find_library("gdal"))'
    /opt/homebrew/lib/libgdal.dylib
    
  2. But, Pyenv-installed Python does not:

    PYENV_VERSION=3.13 pyenv exec python -c 'import ctypes.util; print(ctypes.util.find_library("gdal"))'
    None
    

    Stepping through code shows that the above only searches in:

    • ~/lib/
    • /usr/local/lib/ (no such folder on recent versions of macOS)
    • /lib/ (likewise)
    • /usr/lib/

So, for example, things may magically work when using a Homebrew-installed Python when creating a virtual env using python -m venv venv, or fail when using another.

Aside, rather than hardcoding the paths, one may want the following in settings.py, like used in Cookiecutter Django:

# Assuming `src/project/settings.py`
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent.parent

READ_DOT_ENV_FILE = env.bool("DJANGO_READ_DOT_ENV_FILE", default=False)
if READ_DOT_ENV_FILE:
    # OS environment variables take precedence over variables from .env
    env.read_env(str(BASE_DIR / ".env"))

Along with a .env file such as:

# This needs `export DJANGO_READ_DOT_ENV_FILE=True`

# Make any Python find Homebrew-installed GDAL
GDAL_LIBRARY_PATH=/opt/homebrew/opt/gdal/lib/libgdal.dylib
GEOS_LIBRARY_PATH=/opt/homebrew/opt/geos/lib/libgeos_c.dylib

Or dynamically when running a shell:

export GDAL_LIBRARY_PATH="$(gdal-config --prefix)/libgdal.dylib" 
export GEOS_LIBRARY_PATH="$(geos-config --prefix)/libgeos_c.dylib"

Both also along with the following in settings.py, or just for local testing:

GDAL_LIBRARY_PATH = env("GDAL_LIBRARY_PATH", default="")
GEOS_LIBRARY_PATH = env("GEOS_LIBRARY_PATH", default="")

See also non-Django alternatives such as DYLD_LIBRARY_PATH and DYLD_FALLBACK_LIBRARY_PATH in Add Homebrew libraries to the library search on Apple Silicon/darwin-arm64, or how to find them from other software?

And finally for future search, when not setting GEOS_LIBRARY_PATH, then DATABASES["default"]["ENGINE"] = "django.contrib.gis.db.backends.postgis" would throw:

django.core.exceptions.ImproperlyConfigured: 'django.contrib.gis.db.backends.postgis' isn't an available database backend or couldn't be imported.

Upvotes: 0

Diki Bhuyan
Diki Bhuyan

Reputation: 46

If you are in MAC and Using Anaconda then
step 1: conda install -c conda-forge gdal
step 2: Set this on your Settings.py

GDAL_LIBRARY_PATH='/opt/anaconda3/lib/libgdal.dylib'
GEOS_LIBRARY_PATH='/opt/anaconda3/lib/libgeos_c.dylib'

(It worked for me)

Upvotes: 3

Related Questions