¿Por qué Python no puede encontrar objetos compartidos que están en directorios en sys.path?

124

Estoy intentando importar pycurl:

$ python -c "import pycurl"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: libcurl.so.4: cannot open shared object file: No such file or directory

Ahora libcurl.so.4está adentro /usr/local/lib. Como puede ver, esto está en sys.path:

$ python -c "import sys; print(sys.path)"
['', '/usr/local/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg', 
'/usr/local/lib/python25.zip', '/usr/local/lib/python2.5', 
'/usr/local/lib/python2.5/plat-linux2', '/usr/local/lib/python2.5/lib-tk', 
'/usr/local/lib/python2.5/lib-dynload', 
'/usr/local/lib/python2.5/sitepackages', '/usr/local/lib', 
'/usr/local/lib/python2.5/site-packages']

Cualquier ayuda será apreciada.

BR123
fuente
Vea mi respuesta actualizada, en caso de que no haya configurado LD_LIBRARY_PATHcorrectamente (pensé que a su comentario le faltaban dos puntos).
Vinay Sajip
1
¿Hay algún enlace simbólico roto en algún lugar llamado libcurl.so.4? Me parece que está encontrando el archivo pero no puede abrirlo. Si todo lo demás falla, coloque el intérprete y busque la llamada que falla.
Charles Duffy

Respuestas:

158

sys.pathsolo se buscan módulos de Python. Para las bibliotecas vinculadas dinámicas, las rutas buscadas deben estar en LD_LIBRARY_PATH. Compruebe si LD_LIBRARY_PATHincluye /usr/local/lib, y si no lo hace, agréguelo e intente nuevamente.

Algo más de información ( fuente ):

En Linux, la variable de entorno LD_LIBRARY_PATH es un conjunto de directorios separados por dos puntos donde las bibliotecas deben buscarse primero, antes del conjunto estándar de directorios; Esto es útil al depurar una nueva biblioteca o al usar una biblioteca no estándar para fines especiales. La variable de entorno LD_PRELOAD enumera las bibliotecas compartidas con funciones que anulan el conjunto estándar, tal como lo hace /etc/ld.so.preload. Estos son implementados por el cargador /lib/ld-linux.so. Debo señalar que, aunque LD_LIBRARY_PATH funciona en muchos sistemas tipo Unix, no funciona en todos; por ejemplo, esta funcionalidad está disponible en HP-UX pero como la variable de entorno SHLIB_PATH, y en AIX esta funcionalidad es a través de la variable LIBPATH (con la misma sintaxis, una lista separada por dos puntos).

Actualización: para configurar LD_LIBRARY_PATH, use uno de los siguientes, idealmente en su ~/.bashrc archivo o archivo equivalente:

export LD_LIBRARY_PATH=/usr/local/lib

o

export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

Use el primer formulario si está vacío (equivalente a la cadena vacía, o no está presente), y el segundo formulario si no lo está. Tenga en cuenta el uso de la exportación .

Vinay Sajip
fuente
2
Gracias. Mi LD_LIBRARY_PATH no se configuró, por lo que: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib Pero sigo teniendo el mismo error: $ python -c "import pycurl" Traceback (última llamada más reciente): Archivo "<string>", línea 1, en <module> ImportError: libcurl.so.4: no se puede abrir el archivo de objeto compartido: No
2
También tuve que dar permisos a mi usuario para leer la biblioteca después de configurar la variable LD_LIBRARY_PATH. Ahora finalmente funciona.
José Ricardo
56

Asegúrese de que su módulo libcurl.so esté en la ruta de la biblioteca del sistema, que es distinta y separada de la ruta de la biblioteca de Python.

Una "solución rápida" es agregar esta ruta a una variable LD_LIBRARY_PATH. Sin embargo, configurar ese sistema en todo el sistema (o incluso en toda la cuenta) es una IDEA MALA, ya que es posible configurarlo de tal manera que algunos programas encuentren una biblioteca que no debería, o peor aún, abrir agujeros de seguridad.

Si sus "bibliotecas instaladas localmente" están instaladas en, por ejemplo, / usr / local / lib, agregue este directorio a /etc/ld.so.conf (es un archivo de texto) y ejecute "ldconfig"

El comando ejecutará una utilidad de almacenamiento en caché, pero también creará todos los "enlaces simbólicos" necesarios para que funcione el sistema del cargador. Es sorprendente que el "make install" para libcurl no lo haya hecho ya, pero es posible que no pueda si / usr / local / lib no está en /etc/ld.so.conf ya.

PD: es posible que su /etc/ld.so.conf no contenga más que "incluir ld.so.conf.d / *. Conf". Todavía puede agregar una ruta de directorio después, o simplemente crear un nuevo archivo dentro del directorio desde el que se está incluyendo. No olvide ejecutar "ldconfig" después de él.

Ten cuidado. Hacer esto mal puede arruinar su sistema.

Además: asegúrese de que su módulo Python esté compilado contra ESA versión de libcurl. Si acaba de copiar algunos archivos desde otro sistema, esto no siempre funcionará. En caso de duda, compile sus módulos en el sistema en el que desea ejecutarlos.

Ch'marr
fuente
Gracias, esto funcionó. Me pregunto por qué mi intento anterior de "solución rápida" al cambiar la variable LD_LIBRARY_PATH no lo hizo.
2
Depende de muchos factores. Aquí hay una posibilidad: su código se estaba ejecutando desde apache o cron. Esos programas suelen "limpiar" el entorno, por lo que debe hacer cosas adicionales para obtener las variables de entorno. Por ejemplo, "SetEnv" en apache, o establecer la variable en el archivo crontab para cron. ¡Las posibilidades de errores son infinitas!
Ch'marr
24

También puede configurar LD_RUN_PATH en / usr / local / lib en su entorno de usuario cuando compila pycurl en primer lugar. Esto incrustará / usr / local / lib en el atributo RPATH del módulo de extensión C para que sepa automáticamente dónde encontrar la biblioteca en tiempo de ejecución sin tener que tener LD_LIBRARY_PATH establecido en tiempo de ejecución.

Graham Dumpleton
fuente
44
Como alternativa, el uso python setup.py build_ext --rpath=/usr/local/liben la construcción del módulo de extensión para cocer al horno en el rpath
Kynan
10

Tenía exactamente el mismo problema. Instalé curl 7.19 en / opt / curl / para asegurarme de que no afectaría a curl actual en nuestros servidores de producción. Una vez que vinculé libcurl.so.4 a / usr / lib:

sudo ln -s /opt/curl/lib/libcurl.so /usr/lib/libcurl.so.4

¡Todavía tengo el mismo error! Durf.

Pero ejecutar ldconfig hizo el enlace para mí y funcionó. No es necesario configurar LD_RUN_PATH o LD_LIBRARY_PATH en absoluto. Solo necesitaba ejecutar ldconfig.

Mate
fuente
¿Qué pasa si no tengo el privilegio de sudo? No puedo ejecutar ldconfig? ¿Hay alguna forma de borrar el error anterior entonces?
Prasanna
2
@SPRajagopal: si no tiene privilegios para modificar los atributos del sistema, debe usar el LD_LIBRARY_PATHmétodo de variable de entorno descrito anteriormente. Si no desea establecerlo en su ~/.bashrc(agregar esa configuración no es una buena idea IMO), puede escribir un script de shell que establezca esta variable y luego ejecute python, luego llame a ese script.
MadScientist
8

Como suplemento a las respuestas anteriores, solo estoy tropezando con un problema similar y estoy trabajando completamente con el pitón instalado por defecto.

Cuando llamo al ejemplo de la biblioteca de objetos compartidos que estoy buscando LD_LIBRARY_PATH, obtengo algo como esto:

$ LD_LIBRARY_PATH=/path/to/mysodir:$LD_LIBRARY_PATH python example-so-user.py
python: can't open file 'example-so-user.py': [Errno 2] No such file or directory

Notablemente, ni siquiera se queja de la importación, ¡se queja del archivo fuente!

Pero si fuerzo la carga del objeto usando LD_PRELOAD:

$ LD_PRELOAD=/path/to/mysodir/mypyobj.so python example-so-user.py
python: error while loading shared libraries: libtiff.so.5: cannot open shared object file: No such file or directory

... Inmediatamente recibo un mensaje de error más significativo, ¡sobre una dependencia que falta!

Solo pensé en anotar esto aquí - ¡salud!

sdaau
fuente
¿Estás seguro de que no se trata de un nuevo error antes del error de OP?
David Knipe
1

Yo uso python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0y el archivo compilado .so está debajo de la carpeta de compilación. puede escribir python setup.py --help build_extpara ver las explicaciones de -R y -I

ScutterKey
fuente
1

Para mí, lo que funciona aquí es usar un administrador de versiones como pyenv , que recomiendo encarecidamente para que sus entornos de proyecto y versiones de paquetes estén bien administrados y separados del sistema operativo.

Tuve este mismo error después de una actualización del sistema operativo, pero se solucionó fácilmente con pyenv install 3.7-dev(la versión que uso).

elcortegano
fuente