IPython en Windows no puede importar geopandas

Nov 02 2020

Obtengo un

ImportError: Error al cargar la DLL: no se pudo encontrar el procedimiento especificado.

Error al intentar importar geopandas en Python 3.6. Específicamente, obtengo el error cuando uso ipython pero no cuando uso python. Además, esto afecta a Windows (una máquina virtual de Windows Server 2016) y no a Linux. Encontré algunas publicaciones anteriores sobre esto, o problemas muy similares, pero rechazo su idoneidad ya que no resuelven claramente el problema o lo combinan con instalaciones de pip.

Esta publicación de hace casi dos años, por ejemplo, informa un error similar, pero concluye con un "No importa, hice una instalación pip de geopandas".

Esta publicación de hace poco más de un par de años tiene una respuesta aceptada a pesar de que el póster original comenta que no funcionó para ellos. Se menciona una publicación de blog de Geoff Boeing que he visto antes como un método de trabajo, a pesar de que la publicación de blog proporciona más de un enfoque (una instalación de conda y una secuencia de pasos más manual) y el comentario no aclara qué funcionó para ellos.

Hay una publicación de hace casi dos años y medio que combina los métodos de instalación de conda y pip y no tiene una respuesta aceptada. Hay una sugerencia en un comentario de que, para el comentarista, fue un problema con gdal en conda-forge. Hay una respuesta que se refiere a la publicación de blog de Geoff Boeing nuevamente. La implicación puede ser que la instalación de gdal a través de conda puede ser problemática y, si lo es, entonces se requiere la secuencia manual de pasos. No estoy convencido de que este sea mi problema.

Mi problema ocurre específicamente en una máquina virtual de Windows Server 2016 y al especificar solo el canal conda-forge. Además, de manera pertinente, solo ocurre en ipython (y por lo tanto en los cuadernos de Jupyter) y no en python, por lo tanto:

Cree un entorno especificando el canal de valores predeterminados de conda, especificando python 3.6, ipython y geopandas:

conda create -n test36_defaults -c defaults python=3.6 ipython geopandas

Activa ese entorno:

(test36_2) C:\Users\guy.maskall>conda activate test36_defaults

Inicie un kernel ipython e importe geopandas:

(test36_defaults) C:\Users\guy.maskall>ipython
Python 3.6.12 |Anaconda, Inc.| (default, Sep  9 2020, 00:29:25) [MSC v.1916 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 5.8.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import geopandas as gpd

In [2]:
Do you really want to exit ([y]/n)?

Importó bien.

Del mismo modo, encienda el intérprete de Python directo:

(test36_defaults) C:\Users\guy.maskall>python
Python 3.6.12 |Anaconda, Inc.| (default, Sep  9 2020, 00:29:25) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import geopandas as gpd
>>>

Eso también importó bien.

Ahora cree otro entorno especificando solo conda-forge:

conda create -n test36_cforge -c conda-forge python=3.6 ipython geopandas

Active el entorno y cargue ipython nuevamente para importar geopandas:

(test36_cforge) C:\Users\guy.maskall>ipython
Python 3.6.11 (default, Aug  5 2020, 19:41:03) [MSC v.1916 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 5.8.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import geopandas as gpd
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-a62d01c1d62e> in <module>()
----> 1 import geopandas as gpd

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\geopandas\__init__.py in <module>()
      5 from geopandas.array import points_from_xy  # noqa
      6
----> 7 from geopandas.io.file import _read_file as read_file  # noqa
      8 from geopandas.io.arrow import _read_parquet as read_parquet  # noqa
      9 from geopandas.io.arrow import _read_feather as read_feather  # noqa

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\geopandas\io\file.py in <module>()
      5 import pandas as pd
      6
----> 7 import fiona
      8 import pyproj
      9 from shapely.geometry import mapping

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__init__.py in <module>()
     84 import fiona._loading
     85 with fiona._loading.add_gdal_dll_directories():
---> 86     from fiona.collection import BytesCollection, Collection
     87     from fiona.drvsupport import supported_drivers
     88     from fiona.env import ensure_env_with_credentials, Env

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\collection.py in <module>()
      9 with fiona._loading.add_gdal_dll_directories():
     10     from fiona import compat, vfs
---> 11     from fiona.ogrext import Iterator, ItemsIterator, KeysIterator
     12     from fiona.ogrext import Session, WritingSession
     13     from fiona.ogrext import buffer_to_virtual_file, remove_virtual_file, GEOMETRY_TYPES

ImportError: DLL load failed: The specified procedure could not be found.

In [2]:
Do you really want to exit ([y]/n)?

Entonces eso falló en ipython. Ahora pruébalo usando solo Python directo:

(test36_cforge) C:\Users\guy.maskall>python
Python 3.6.11 (default, Aug  5 2020, 19:41:03) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import geopandas as gpd
>>>

Eso funciona.

Una de las respuestas en las publicaciones de SO anteriores destaca GDAL, Fiona, pyproj, rtree y bien formada. Al comparar la salida de conda listentre los dos entornos anteriores, obtengo exactamente las mismas versiones de todos ellos. Todos menos rtree tienen la misma estructura. Así que tengo:

gdal                      3.1.4            py36h214b664_0    conda-forge  
fiona                     1.8.17           py36hdef4c2b_1 conda-forge  
pyproj                    2.6.1.post1      py36hfcef96e_3 conda-forge  
shapely                   1.7.1            py36h6dc46f0_1 conda-forge

y

rtree                     0.9.4            py36h9a6d676_1    conda-forge

(asociado con el env que no funcionó) vs

rtree                     0.9.4            py36h21ff451_1

(en el env que funciona).

Lo que me confunde bastante es que a pesar de algunas publicaciones que implican a gdal, y mi salida de error anterior implicando a fiona cargando gdal (creo), ambos entornos parecen tener exactamente la misma versión y compilación de gdal y fiona, y el error solo ocurre en el ipython kernel y no en python.

Es importante para mí poder replicar entornos fácilmente, por lo que se prefiere conda. Tengo otros requisitos además de conseguir que se carguen los geopandas. Por ejemplo, uso datacube, que recomienda python 3.6. Anteriormente estaba ejecutando una versión superior de Python y me gustaría tener un entorno de Python 3.6 en funcionamiento para poder ver si eso resuelve otro problema que estaba teniendo. Me gustaría reducir qué está causando este error, ya que quiero poder editar fácilmente mi conda env yaml para probar diferentes entornos, y es posible que deba especificar varios canales ya que un sospechoso (para otro problema) es el kit de herramientas de solicitud , que solo parece estar disponible en una versión inferior a 3 del canal esrf-bcu, pero esa es otra historia.

Entonces, ¿alguien puede ayudar a señalar

  • ¿Cuál es exactamente el paquete / versión / compilación que podría estar causando esto?
  • ¿Por qué demonios, incluso en el entorno problemático, solo afecta a ipython?

Hay una pequeña diferencia en la versión de Python (3.6.11 falla y 3.6.12 tiene éxito), y eso es algo que puedo explorar, pero eso todavía me deja la pregunta de por qué la diferencia entre ipython vs python.

En otras noticias, odio Windows.

Importando fiona y ruta DLL

Actualización 2020/11/02 Como el error parece centrarse en fiona, lo he reducido a eso. En el shell del indicador de anaconda, ejecuté set PYTHONVERBOSE=1, luego cargué ipython e intenté importar fiona:

In [1]: import fiona
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__pycache__\__init__.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__init__.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\__pycache__\\__init__.cpython-36.pyc'
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__pycache__\_loading.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\_loading.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\__pycache__\\_loading.cpython-36.pyc'
import 'fiona._loading' # <_frozen_importlib_external.SourceFileLoader object at 0x0000020344DC0C88>
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\__pycache__\socket.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\socket.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\__pycache__\\socket.cpython-36.pyc'
# extension module '_socket' loaded from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\DLLs\\_socket.pyd'
# extension module '_socket' executed from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\DLLs\\_socket.pyd'
import '_socket' # <_frozen_importlib_external.ExtensionFileLoader object at 0x0000020344DCED30>
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\__pycache__\selectors.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\selectors.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\__pycache__\\selectors.cpython-36.pyc'
import 'selectors' # <_frozen_importlib_external.SourceFileLoader object at 0x0000020344DD9358>
import 'socket' # <_frozen_importlib_external.SourceFileLoader object at 0x0000020344DCE198>
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__pycache__\collection.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\collection.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\__pycache__\\collection.cpython-36.pyc'
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__pycache__\compat.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\compat.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\__pycache__\\compat.cpython-36.pyc'
import 'fiona.compat' # <_frozen_importlib_external.SourceFileLoader object at 0x0000020344DE76D8>
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__pycache__\vfs.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\vfs.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\__pycache__\\vfs.cpython-36.pyc'
import 'fiona.vfs' # <_frozen_importlib_external.SourceFileLoader object at 0x0000020344DE7780>
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-4c762272c079> in <module>()
----> 1 import fiona

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _find_and_load(name, import_)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _find_and_load_unlocked(name, import_)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _load_unlocked(spec)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap_external.py in exec_module(self, module)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__init__.py in <module>()
     84 import fiona._loading
     85 with fiona._loading.add_gdal_dll_directories():
---> 86     from fiona.collection import BytesCollection, Collection
     87     from fiona.drvsupport import supported_drivers
     88     from fiona.env import ensure_env_with_credentials, Env

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _find_and_load(name, import_)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _find_and_load_unlocked(name, import_)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _load_unlocked(spec)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap_external.py in exec_module(self, module)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\collection.py in <module>()
      9 with fiona._loading.add_gdal_dll_directories():
     10     from fiona import compat, vfs
---> 11     from fiona.ogrext import Iterator, ItemsIterator, KeysIterator
     12     from fiona.ogrext import Session, WritingSession
     13     from fiona.ogrext import buffer_to_virtual_file, remove_virtual_file, GEOMETRY_TYPES

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _find_and_load(name, import_)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _find_and_load_unlocked(name, import_)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _load_unlocked(spec)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in module_from_spec(spec)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap_external.py in create_module(self, spec)

C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\importlib\_bootstrap.py in _call_with_frames_removed(f, *args, **kwds)

ImportError: DLL load failed: The specified procedure could not be found.

Pero luego salgo de ipython y enciendo python directo e intento importar fiona, obtengo una tonelada más de salida (ahorrándote todo, pero centrándome en la parte donde ipython parece rescatar):

...

import 'fiona.compat' # <_frozen_importlib_external.SourceFileLoader object at 0x00000289AC978470>
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__pycache__\vfs.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\vfs.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\__pycache__\\vfs.cpython-36.pyc'
import 'fiona.vfs' # <_frozen_importlib_external.SourceFileLoader object at 0x00000289AC997550>
# extension module 'fiona.ogrext' loaded from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\ogrext.cp36-win_amd64.pyd'
# extension module 'fiona._geometry' loaded from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\_geometry.cp36-win_amd64.pyd'
# extension module 'fiona._err' loaded from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\_err.cp36-win_amd64.pyd'
# extension module 'fiona._err' executed from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\_err.cp36-win_amd64.pyd'
import 'fiona._err' # <_frozen_importlib_external.ExtensionFileLoader object at 0x00000289AC9EE7F0>
# C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\__pycache__\errors.cpython-36.pyc matches C:\Users\guy.maskall\anaconda3\envs\test36_cforge\lib\site-packages\fiona\errors.py
# code object from 'C:\\Users\\guy.maskall\\anaconda3\\envs\\test36_cforge\\lib\\site-packages\\fiona\\__pycache__\\errors.cpython-36.pyc'
import 'fiona.errors' # <_frozen_importlib_external.SourceFileLoader object at 0x00000289AC9EEFD0>

...

¡Esto es sumergirse en las tripas que realmente no conozco! Pero parece que puedo decir con seguridad algunas cosas:

  • Tanto ipython como python se importan desde la misma ruta (como era de esperar)
  • Después del punto en el que ipython se recupera, Python informa / comenta sobre la carga del módulo de extensión fiona.ogrext, que es el último error informado en el rastreo.
  • Además, ese error está dentro del contexto de fiona._loading.add_gdal_dll_directories (), lo que sugiere que tiene algo que ver con las rutas DLL

Pero de nuevo, vuelvo a tener que preguntar por qué esta función, o encontrar las DLL, se comporta de manera diferente en ipython en comparación con python.

Además, he verificado que veo este mismo comportamiento en Windows 10 Pro versión 2004.

Respuestas

doctorG Nov 03 2020 at 00:44

El problema de importación específico se ha resuelto simplemente especificando python 3.6.12 desde 3.6.11, así:

conda create -n test36_12_cforge -c conda-forge python=3.6.12 ipython geopandas
(test36_12_cforge) C:\Users\guy.maskall>ipython
Python 3.6.12 |Anaconda, Inc.| (default, Sep  9 2020, 00:29:25) [MSC v.1916 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 5.8.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import geopandas as gpd

In [2]:
Do you really want to exit ([y]/n)?

(test36_12_cforge) C:\Users\guy.maskall>ipython
Python 3.6.12 |Anaconda, Inc.| (default, Sep  9 2020, 00:29:25) [MSC v.1916 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 5.8.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import fiona

In [2]:
Do you really want to exit ([y]/n)?

Soy reacio a aceptar mi propia respuesta. Por una cerveza, si alguna vez nos encontramos, ¿alguien puede explicar por qué habría esta diferencia en el comportamiento dependiendo de si la importación se realiza desde ipython o python?