modules - python importerror: cannot import name
¿Qué significa en realidad "símbolo no encontrado/esperado en: espacio de nombres plano"? (5)
Descripción
El problema se originó al mezclar objetos que se compilaron con libc++
y objetos que se compilaron con libstdc++
.
En nuestro caso, la biblioteca myMod.so
(compilada con libstdc++
) necesita boost-python
que compiló con libstdc++
( boost-python-libstdc++
partir de ahora). Cuando boost-python
es boost-python-libstdc++
, funcionará bien. De lo contrario, en la computadora que su boost-python
ha compilado con libc++
(u otra biblioteca de c ++), tendrá un problema al cargarlo y ejecutarlo.
En nuestro caso, sucede porque los desarrolladores de libc++
cambiaron intencionalmente el nombre de todos sus símbolos para evitar que (y guardarlo) mezclen el código de su biblioteca y el código de uno diferente: myMod.so
necesita una función que tome un argumento del tipo. En libc++
, el nombre de este tipo es std::__1::pair
. Por lo tanto, este símbolo no fue encontrado.
Para entender por qué es malo mezclar dos versiones de la misma API, considere esta situación: hay dos bibliotecas: Foo
y Bar
. Ambos tienen una función que toma un std::string
y lo usa para algo, pero usa una biblioteca de c ++ diferente. Cuando una std::string
creada por Foo
se pase a Bar
, Bar
pensará que esta es una instancia de la std::string
de su biblioteca c ++ y luego pueden suceder cosas malas (son objetos completamente diferentes).
Nota : En algunos casos, no habría ningún problema con dos o más versiones diferentes de la misma API en partes completamente diferentes de un programa. Habrá un problema si pasarán los objetos de esta API entre ellos. Sin embargo, comprobar que puede ser muy difícil, especialmente si pasan el objeto API solo como miembro de otro objeto. Además, la función de inicialización de una biblioteca puede hacer cosas que no deberían ocurrir dos veces. Otra versión puede hacer estas cosas de nuevo.
¿Cómo resolver eso?
Siempre puedes recompilar tus bibliotecas y hacerlas coincidir entre sí.
Puede vincular
boost-python
a su biblioteca como una biblioteca estática. Luego, funcionará en casi todas las computadoras (incluso una que no tieneboost-python
instalado). Ver más sobre eso here .
Resumen
myMod.so
necesita otra versión de boost-python
, una que compile con una biblioteca c ++ específica. Por lo tanto, no funcionaría con ninguna otra versión.
Cuando importo un módulo que construí, recibo este error relacionado con boost-python:
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: dlopen(./myMod.so, 2): Symbol not found: __ZN5boost6python7objects15function_objectERKNS1_11py_functionERKSt4pairIPKNS0_6detail7keywordES9_E
Referenced from: ./myMod.so
Expected in: flat namespace
in ./myMod.so
¿Qué significa esto realmente? ¿Por qué se planteó este error?
El símbolo no encontrado significa que no se encontró la definición de la función o variable declarada. Cuando se compila un archivo de encabezado de un objeto compartido con su programa, el enlazador agrega símbolos de funciones y objetos declarados a su programa compilado. Cuando el cargador del sistema operativo carga su programa, los símbolos se resuelven para que se cargue su definición. Es solo en este momento donde si falta la implementación, el cargador se queja de que no pudo encontrar la definición debido a que puede fallar al resolver la ruta real a la biblioteca o la biblioteca en sí no se compiló con el archivo de implementación / fuente donde La definición de la función u objeto reside. Hay un buen artículo sobre esto en la revista de linux http://www.linuxjournal.com/article/6463 .
Esto es lo que he aprendido (osx):
Si se supone que esto funciona (es decir, funciona en otra computadora), es posible que esté experimentando problemas con Clang / GCC. Para depurar esto, use otool -l
en el archivo .so que está generando el error, o en una biblioteca sospechosa (en mi ejemplo es un archivo dylib boost-python) y examine el contenido. Cualquier cosa en la carpeta / System / se construye con clang, y se debe instalar en otro lugar con el compilador gcc. Nunca borres nada de la carpeta / System.
Me encuentro con el mismo problema.
Expected in: flat namespace
Añadir la bandera del enlazador soluciona el problema
-lboost_python37
cambie el nombre de la biblioteca dinámica al que está instalado en el sistema operativo.
Por cierto, mi sistema operativo es macOS High Sierra y uso brew para instalar boost_python3
.
.so
archivos .so
son bibliotecas dinámicas (por lo tanto, = objeto compartido). En Windows se llaman .dll
(biblioteca de enlace dinámico). Contienen código compilado que contiene funciones disponibles para el uso de cualquier ejecutable que las vincula.
Lo que es importante notar aquí es que esos .so
no son archivos de Python. Probablemente se compilaron a partir del código C o C ++ y contienen funciones públicas que se pueden usar desde el código Python (consulte la documentación en Extender Python con C o C ++ ).
En tu caso, bueno, tienes un corrupto .so
. Intente volver a instalar las bibliotecas afectadas, Python o ambos.