2009-05-13 8 views
29

¿Cómo se actualiza esta variable de entorno en tiempo de ejecución para que ctypes pueda cargar una biblioteca donde sea? Intenté lo siguiente y ninguno parece funcionar.Cambiando LD_LIBRARY_PATH en tiempo de ejecución para ctypes

from ctypes import * 
os.environ['LD_LIBRARY_PATH'] = "/home/starlon/Projects/pyCFA635/lib" 
os.putenv('LD_LIBRARY_PATH', "/home/starlon/Projects/pyCFA635/lib") 
lib = CDLL("libevaluator.so") 

Respuesta

35

En el momento en un programa como Python está en funcionamiento, el cargador dinámico (ld.so.1 o algo similar) ya ha leído LD_LIBRARY_PATH y no note ningún cambio a partir de entonces. Por lo tanto, a menos que el software Python mismo evalúe LD_LIBRARY_PATH y lo use para compilar el posible nombre de ruta de la biblioteca para dlopen() o una función equivalente, la configuración de la variable en el script no tendrá efecto.

Dado que usted dice que no funciona, parece plausible suponer que Python no compila y prueba todos los posibles nombres de biblioteca; probablemente solo confía en LD_LIBRARY_PATH.

+5

esto diagnostica el problema pero no lo resuelve. – dbliss

13

CDLL se puede pasar un nombre de ruta completo, así que por ejemplo estoy usando lo siguiente en uno de mis scripts donde .so está en el mismo directorio que el script de python.

import os 
path = os.path.dirname(os.path.realpath(__file__)) 
dll = CDLL("%s/iface.so"%path) 

En su caso, lo siguiente debería ser suficiente.

from ctypes import * 
lib = CDLL("/home/starlon/Projects/pyCFA635/lib/libevaluator.so") 
21

Incluso si se le da una ruta de acceso completa a CDLL o cdll.LoadLibrary(), es posible que aún tenga que configurar LD_LIBRARY_PATH antes de invocar Python. Si la biblioteca compartida que carga explícitamente hace referencia a otra biblioteca compartida y no se establece "rpath" en .so para esa biblioteca, no se encontrará, incluso si ya se ha cargado. Un rpath en una biblioteca especifica una ruta de búsqueda que se utilizará para buscar otras bibliotecas necesarias para esa biblioteca

Por ejemplo, tengo un caso de un conjunto de bibliotecas de terceros interdependientes que no he creado. b.so hace referencia a.so. Incluso si me carga a.so con antelación:

ctypes.cdll.LoadLibrary('/abs/path/to/a.so') 
ctypes.cdll.LoadLibrary('/abs/path/to/b.so') 

consigo un error en la segunda carga, porque b.so se refiere a simplemente 'a.so', sin un rpath, y así b.so doesn' Sé que ese es el correcto. Así que tengo que establecer LD_LIBRARY_PATH de antemano para incluir '/ abs/path/to'.

Para evitar tener que establecer LD_LIBRARY_PATH, modifique la entrada rpath en los archivos .so. En Linux, hay dos utilidades que encontré que hacen esto: chrpath y patchelf. Chrpath está disponible en los repositorios de Ubuntu. No puede cambiar rpath en .so que nunca tuvo uno. patchelf es más flexible.

1

Compilar su binario con un rpath relativa al directorio de trabajo actual como:

gcc -shared -o yourbinary.so yoursource.c otherbinary.so \ 
    -Wl,-rpath='.',-rpath='./another/relative/rpath' -fpic 

Entonces, usted es capaz de cambiar el directorio de trabajo en Python en tiempo de ejecución:

import os 
os.chdir('/path/to/your/binaries') 

gusta esta , el cargador también encuentra otras bibliotecas dinámicas como otherbinary.so

+0

Esto solo funciona cuando el directorio de trabajo del proceso que carga la biblioteca es el directorio de la biblioteca. De lo contrario, la ruta de tiempo de ejecución relativa no puede encontrar la dependencia, cuyo directorio es relativo a la biblioteca. – danny

Cuestiones relacionadas