Python utilise la variable d'environnement PYTHONPATH
pour déterminer dans quels dossiers il doit rechercher les modules. Vous pouvez jouer avec lui en modifiant sys.path
, Qui fonctionne bien pour les modules Python purs. Mais quand un module utilise des fichiers objets partagés ou des bibliothèques statiques, il recherche ceux dans LD_LIBRARY_PATH
(Sous linux), mais cela ne peut pas être changé aussi facilement et dépend de la plate-forme pour autant que je sache.
La solution rapide pour ce problème est bien sûr de définir la variable d'environnement ou d'appeler le script comme LD_LIBRARY_PATH=. ./script.py
, Mais vous devrez ensuite le redéfinir pour chaque nouveau Shell que vous ouvrez. De plus, les fichiers .so
Dans mon cas seront toujours dans le même répertoire que le fichier .py
, Mais peuvent très bien être déplacés vers un autre chemin absolu, donc je voudrais les définir automatiquement chaque fois que j'invoque le script.
Comment puis-je modifier le chemin dans lequel l'interpréteur Python recherche les bibliothèques indépendamment de la plate-forme lors de l'exécution?
J'ai déjà essayé os.environ['LD_LIBRARY_PATH'] = os.getcwd()
, mais en vain.
J'utiliserais:
import os
os.environ['LD_LIBRARY_PATH'] = os.getcwd() # or whatever path you want
Cela définit le LD_LIBRARY_PATH
variable d'environnement pour la durée/durée de vie de l'exécution du processus en cours uniquement.
EDIT: il semble que cela doit être défini avant de démarrer Python: Modification de LD_LIBRARY_PATH au moment de l'exécution pour les ctypes
Je suggérerais donc d'aller avec un wrapper .sh
(ou .py
si vous insistez) script. En outre, comme l'a souligné @chepner, vous pouvez envisager d'installer votre .so
fichiers dans un emplacement standard (dans virtualenv).
Voir aussi Définition de LD_LIBRARY_PATH depuis Python
Ma solution à ce problème est de mettre cela comme la première ligne d'un script Python (au lieu du Shebang habituel):
exec env LD_LIBRARY_PATH=/some/path/to/lib /path/to/specific/python -x "$0" "$@"
Et voici comment cela fonctionne:
Python, quand obtient les valeurs des variables d'environnement comme dans os.environ[‘LD_LIBRARY_PATH’]
ou os.environ[‘PATH’]
, il copie les valeurs, dans un dictionnaire, à partir de l'environnement de son processus parent, généralement bash (l'environnement du processus bash est transféré au processus enfant, l'instance python en cours d'exécution).
vous pouvez voir cette section de variable d'environnement avec la sortie de commande env
de bash.
vous pouvez également voir/lire ces données env à partir de /proc/<pid>/environ
, en introduisant une boucle infinie (while 1: pass
) après avoir modifié une variable d'environnement.
Si vous voyez/lisez cette valeur de variable/données de /proc/<pid>/environ
après l'avoir modifié à l'intérieur du script python, vous pourriez voir que les données de la variable réelle ne sont pas modifiées, bien que le script python montre un valeur de clé de dictionnaire modifiée, mise à jour.
Que se passe-t-il réellement lorsque vous modifiez une variable env à l'intérieur du script python, comme dans os.environ['LD_LIBRARY_PATH']='/<new_location>'
, c'est qu'il met juste à jour la valeur dans le dictionnaire local, qui n'est pas mappée à la section variable env du processus. Par conséquent, il ne se propagera pas tout le temps pour se refléter dans l'environnement du processus actuel, car NIQUEMENT un dictionnaire local a été modifié/mis à jour/rempli.
Par conséquent, si nous voulons que la nouvelle variable d'environnement soit reflétée, nous devons remplacer l'image mémoire du processus par de nouvelles données de variable d'environnement, en utilisant execv
.
Exemple:
new_lib = '/<new_location>'
if not new_lib in os.environ['LD_LIBRARY_PATH']:
os.environ['LD_LIBRARY_PATH'] += ':'+new_lib
try:
os.execv(sys.argv[0], sys.argv)
except Exception as e:
sys.exit('EXCEPTION: Failed to Execute under modified environment, '+e)
import xyz
#do something else
Limitation: Idéalement, python ne devrait pas permettre une telle modification de os.environ
variables. Mais comme il n'y a pas de type de données de dictionnaire constant, il permet de modifier la variable de données. Il est absolument inutile de modifier les valeurs, car cela n'a rien d'utile à refléter dans l'environnement réel du processus en cours d'exécution, à moins que execv
ne soit utilisé.