Reputation: 2305
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
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:
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
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
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