matplotlib / basemap

Plot on map projections (with coastlines and political boundaries) using matplotlib
MIT License
779 stars 392 forks source link

Basemap can't import when used with a virtual environment #489

Closed TD22057 closed 2 years ago

TD22057 commented 4 years ago

I have a conda environment with MPL + basemap installed in it. I'm using a virtual environment built from that conda environment to install other software. When python is run from the venv, basemap fails to import because it uses sys.prefix to find the share directory which isn't correct. In this case, sys.prefix is the venv, not the base system where basemap is installed.

The problem is this line in init.py: basemap_datadir = os.path.join(sys.prefix, 'share', 'basemap')

IMO, the correct way to do this is to find the site packages directories and search for the share dir relative to both of them. /opt/base is a conda env w/ python and mpl+basemap in it. /home/user/venv is the virtual env.

>>> site.getsitepackages()
['/home/user/venv/lib/python3.7/site-packages', 
  '/opt/base/lib/python3.7/site-packages']
molinav commented 3 years ago

Unfortunately I cannot help with this, since it is not a problem with the basemap repository, but with how basemap is bundled for Anaconda. The basemap repository defines the basemap_datadir in the following manner inside __init__.py:

    basemap_datadir = os.sep.join([os.path.dirname(__file__), 'data'])

so it tries to find the data folder relative to the location of the basemap installation, and this approach should work with virtual environments too. Later, in the basemap repository for Anaconda (https://github.com/conda-forge/basemap-feedstock), the following patch is applied:

--- basemap-1.2.1rel.orig/lib/mpl_toolkits/basemap/__init__.py  2019-08-07 22:03:01.000000000 -0300
+++ basemap-1.2.1rel/lib/mpl_toolkits/basemap/__init__.py   2019-08-08 11:15:02.145868394 -0300
@@ -53,15 +53,10 @@
 import _geoslib
 import functools

-# basemap data files now installed in lib/matplotlib/toolkits/basemap/data
-# check to see if environment variable BASEMAPDATA set to a directory,
-# and if so look for the data there.
-if 'BASEMAPDATA' in os.environ:
-    basemap_datadir = os.environ['BASEMAPDATA']
-    if not os.path.isdir(basemap_datadir):
-        raise RuntimeError('Path in environment BASEMAPDATA not a directory')
+if os.name == 'nt':
+    basemap_datadir = os.path.join(sys.prefix, 'Library', 'share', 'basemap')
 else:
-    basemap_datadir = os.sep.join([os.path.dirname(__file__), 'data'])
+    basemap_datadir = os.path.join(sys.prefix, 'share', 'basemap')

 __version__ = '1.2.1'

and here is where your issue (which is totally right) is introduced. It would be great if you can address them this problem directly in the Issues at https://github.com/conda-forge/basemap-feedstock so that they are aware of it and update the patch file.

molinav commented 2 years ago

I am closing this issue since it is a problem on how things are packaged in Anaconda. The next release of basemap (1.3.0) should support virtual environments flawlessly because the data assets are provided as additional packages living in the namespace basemap-data (at least if using pip and standard virtual environments).