Warum kann Python keine freigegebenen Objekte finden, die sich in Verzeichnissen in sys.path befinden?

124

Ich versuche zu importieren 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

Jetzt libcurl.so.4ist in /usr/local/lib. Wie Sie sehen können, ist dies in 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']

Jede Hilfe wird sehr geschätzt.

BR123
quelle
Siehe meine aktualisierte Antwort, falls Sie nicht LD_LIBRARY_PATHrichtig eingestellt haben (ich dachte, Ihr Kommentar hat einen fehlenden Doppelpunkt).
Vinay Sajip
1
Gibt es irgendwo einen defekten Symlink namens libcurl.so.4? Es sieht für mich so aus, als würde es die Datei finden, aber nicht öffnen können. Wenn alles andere fehlschlägt, suchen Sie den Dolmetscher und suchen Sie nach dem fehlgeschlagenen Anruf.
Charles Duffy

Antworten:

158

sys.pathwird nur nach Python-Modulen gesucht. Bei dynamisch verknüpften Bibliotheken müssen sich die gesuchten Pfade in befinden LD_LIBRARY_PATH. Überprüfen Sie, ob Ihre LD_LIBRARY_PATHIncludes enthalten sind /usr/local/lib, und fügen Sie sie erneut hinzu, falls dies nicht der Fall ist.

Weitere Informationen ( Quelle ):

Unter Linux ist die Umgebungsvariable LD_LIBRARY_PATH eine durch Doppelpunkte getrennte Gruppe von Verzeichnissen, nach denen zuerst vor der Standardgruppe von Verzeichnissen nach Bibliotheken gesucht werden sollte. Dies ist nützlich, wenn Sie eine neue Bibliothek debuggen oder eine nicht standardmäßige Bibliothek für spezielle Zwecke verwenden. Die Umgebungsvariable LD_PRELOAD listet gemeinsam genutzte Bibliotheken mit Funktionen auf, die den Standardsatz überschreiben, genau wie /etc/ld.so.preload. Diese werden vom Loader /lib/ld-linux.so implementiert. Ich sollte beachten, dass LD_LIBRARY_PATH zwar auf vielen Unix-ähnlichen Systemen funktioniert, aber nicht auf allen. Diese Funktionalität ist beispielsweise unter HP-UX verfügbar, aber als Umgebungsvariable SHLIB_PATH und unter AIX erfolgt diese Funktionalität über die Variable LIBPATH (mit derselben Syntax eine durch Doppelpunkte getrennte Liste).

Update:LD_LIBRARY_PATH Verwenden Sie zum Festlegen eine der folgenden Optionen, idealerweise in Ihrer ~/.bashrc oder einer gleichwertigen Datei:

export LD_LIBRARY_PATH=/usr/local/lib

oder

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

Verwenden Sie das erste Formular, wenn es leer ist (entspricht der leeren Zeichenfolge oder ist überhaupt nicht vorhanden), und das zweite Formular, wenn es nicht vorhanden ist. Beachten Sie die Verwendung des Exports .

Vinay Sajip
quelle
2
Vielen Dank. Mein LD_LIBRARY_PATH wurde nicht festgelegt, also: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib Aber ich erhalte immer noch den gleichen Fehler: $ python -c "pycurl importieren" Traceback (letzter Aufruf zuletzt): Datei "<string>", Zeile 1, in <module> ImportError: libcurl.so.4: freigegebene Objektdatei kann nicht geöffnet werden: Keine solche Datei oder kein solches Verzeichnis
2
Ich musste meinem Benutzer auch die Berechtigung zum Lesen der Bibliothek erteilen, nachdem er die Variable LD_LIBRARY_PATH festgelegt hatte. Jetzt funktioniert es endlich.
José Ricardo
56

Stellen Sie sicher, dass sich Ihr libcurl.so-Modul im Systembibliothekspfad befindet, der sich vom Python-Bibliothekspfad unterscheidet.

Eine "schnelle Lösung" besteht darin, diesen Pfad einer LD_LIBRARY_PATH-Variablen hinzuzufügen. Das systemweite (oder sogar kontoweite) Einstellen ist jedoch eine SCHLECHTE IDEE, da es möglich ist, es so einzustellen, dass einige Programme eine Bibliothek finden, die keine oder noch schlimmer Sicherheitslücken öffnen sollte.

Wenn Ihre "lokal installierten Bibliotheken" beispielsweise in / usr / local / lib installiert sind, fügen Sie dieses Verzeichnis zu /etc/ld.so.conf hinzu (es ist eine Textdatei) und führen Sie "ldconfig" aus.

Der Befehl führt ein Caching-Dienstprogramm aus, erstellt jedoch auch alle erforderlichen "symbolischen Links", die für die Funktion des Loader-Systems erforderlich sind. Es ist überraschend, dass die "make install" für libcurl dies nicht bereits getan hat, aber es ist möglich, dass dies nicht möglich ist, wenn / usr / local / lib nicht bereits in /etc/ld.so.conf vorhanden ist.

PS: Möglicherweise enthält Ihre /etc/ld.so.conf nur "include ld.so.conf.d / *. Conf". Sie können danach noch einen Verzeichnispfad hinzufügen oder einfach eine neue Datei in dem Verzeichnis erstellen, aus dem sie aufgenommen wird. Vergessen Sie nicht, danach "ldconfig" auszuführen.

Achtung. Wenn Sie dies falsch verstehen, kann dies Ihr System durcheinander bringen.

Zusätzlich: Stellen Sie sicher, dass Ihr Python-Modul für DIESE Version von libcurl kompiliert ist. Wenn Sie nur einige Dateien von einem anderen System kopiert haben, funktioniert dies nicht immer. Kompilieren Sie im Zweifelsfall Ihre Module auf dem System, auf dem Sie sie ausführen möchten.

Ch'marr
quelle
Danke - das hat funktioniert. Ich frage mich, warum meine zuvor versuchte "Schnellkorrektur" zum Ändern der Variablen LD_LIBRARY_PATH dies nicht tat.
2
Kommt auf viele Faktoren an. Hier ist eine Möglichkeit: Ihr Code wurde von Apache oder Cron ausgeführt. Diese Programme "bereinigen" normalerweise die Umgebung, sodass Sie zusätzliche Aufgaben ausführen müssen, um Umgebungsvariablen abzurufen. Beispiel: "SetEnv" in Apache oder Festlegen der Variablen direkt in der crontab-Datei für cron. Die Möglichkeiten für Fehler sind endlos!
Ch'marr
24

Sie können LD_RUN_PATH auch in Ihrer Benutzerumgebung auf / usr / local / lib setzen, wenn Sie pycurl zuerst kompilieren. Dadurch wird / usr / local / lib in das RPATH-Attribut des C-Erweiterungsmoduls eingebettet, sodass automatisch erkannt wird, wo sich die Bibliothek zur Laufzeit befindet, ohne dass LD_LIBRARY_PATH zur Laufzeit festgelegt werden muss.

Graham Dumpleton
quelle
4
Alternativ können Sie python setup.py build_ext --rpath=/usr/local/libbeim Erstellen
kynan
10

Hatte genau das gleiche Problem. Ich habe curl 7.19 in / opt / curl / installiert, um sicherzustellen, dass das aktuelle Curl auf unseren Produktionsservern nicht beeinträchtigt wird. Sobald ich libcurl.so.4 mit / usr / lib verknüpft habe:

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

Ich habe immer noch den gleichen Fehler! Durf.

Aber mit ldconfig wird die Verknüpfung für mich hergestellt und das hat funktioniert. LD_RUN_PATH oder LD_LIBRARY_PATH müssen überhaupt nicht festgelegt werden. Muss nur ldconfig ausführen.

Matt
quelle
Was ist, wenn ich kein Sudo-Privileg habe? Ich kann ldconfig nicht ausführen? Gibt es dann eine Möglichkeit, den obigen Fehler zu beheben?
Prasanna
2
@SPRajagopal: Wenn Sie keine Berechtigungen zum Ändern der Systemattribute haben, müssen Sie die LD_LIBRARY_PATHoben beschriebene Umgebungsvariablenmethode verwenden. Wenn Sie es nicht in Ihrer festlegen möchten ~/.bashrc(das Hinzufügen dieser Einstellung ist keine gute Idee, IMO), können Sie ein Shell-Skript schreiben, das diese Variable festlegt, dann Python ausführt und dieses Skript aufruft.
MadScientist
8

Als Ergänzung zu den obigen Antworten stoße ich nur auf ein ähnliches Problem und arbeite vollständig mit der standardmäßig installierten Python.

Wenn ich das Beispiel der gemeinsam genutzten Objektbibliothek aufrufe, mit der ich suche LD_LIBRARY_PATH, erhalte ich ungefähr Folgendes:

$ 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

Insbesondere beschwert es sich nicht einmal über den Import - es beschwert sich über die Quelldatei!

Aber wenn ich das Laden des Objekts erzwinge, indem ich 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

... Ich erhalte sofort eine aussagekräftigere Fehlermeldung - über eine fehlende Abhängigkeit!

Ich dachte nur, ich würde das hier unten notieren - Prost!

sdaau
quelle
Sind Sie sicher, dass dies kein neuer Fehler ist, der vor dem OP-Fehler auftritt?
David Knipe
1

Ich benutze python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0und die kompilierte .so-Datei befindet sich unter dem Build-Ordner. Sie können eingeben python setup.py --help build_ext, um die Erklärungen von -R und -I anzuzeigen

ScutterKey
quelle
1

Für mich funktioniert hier die Verwendung eines Versionsmanagers wie pyenv . Ich empfehle dringend, Ihre Projektumgebungen und Paketversionen gut zu verwalten und von denen des trennen.

Ich hatte den gleichen Fehler nach einem Betriebssystem-Update, konnte aber leicht mit pyenv install 3.7-dev(der von mir verwendeten Version) behoben werden .

elcortegano
quelle