Dlaczego Python nie może znaleźć obiektów współdzielonych, które znajdują się w katalogach w sys.path?

125

Próbuję zaimportować 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

Teraz libcurl.so.4jest w /usr/local/lib. Jak widać, jest to 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']

Każda pomoc będzie bardzo mile widziana.

BR123
źródło
Zobacz moją zaktualizowaną odpowiedź, na wypadek gdybyś nie ustawił LD_LIBRARY_PATHpoprawnie (myślałem, że w Twoim komentarzu brakuje dwukropka).
Vinay Sajip
1
Czy w miejscu o nazwie libcurl.so.4 jest uszkodzony link symboliczny? Wydaje mi się, że znajduje plik, ale nie może go otworzyć. Jeśli wszystko inne zawiedzie, ustaw tłumacza i poszukaj połączenia, które się nie powiodło.
Charles Duffy,

Odpowiedzi:

158

sys.pathjest przeszukiwany tylko pod kątem modułów Pythona. W przypadku dynamicznie połączonych bibliotek przeszukiwane ścieżki muszą znajdować się w LD_LIBRARY_PATH. Sprawdź, czy LD_LIBRARY_PATHzawiera /usr/local/lib, a jeśli nie, dodaj go i spróbuj ponownie.

Więcej informacji ( źródło ):

W Linuksie zmienna środowiskowa LD_LIBRARY_PATH jest zbiorem katalogów oddzielonych dwukropkami, w których najpierw należy szukać bibliotek, przed standardowym zestawem katalogów; jest to przydatne podczas debugowania nowej biblioteki lub używania niestandardowej biblioteki do specjalnych celów. Zmienna środowiskowa LD_PRELOAD zawiera listę bibliotek współdzielonych z funkcjami, które przesłaniają zestaw standardowy, tak jak robi to /etc/ld.so.preload. Są one implementowane przez program ładujący /lib/ld-linux.so. Powinienem zauważyć, że chociaż LD_LIBRARY_PATH działa na wielu systemach typu Unix, nie działa na wszystkich; na przykład ta funkcja jest dostępna w systemie HP-UX, ale jako zmienna środowiskowa SHLIB_PATH, aw systemie AIX jest dostępna za pośrednictwem zmiennej LIBPATH (z tą samą składnią, listą oddzieloną dwukropkami).

Aktualizacja: aby ustawić LD_LIBRARY_PATH, użyj jednego z następujących, najlepiej w swoim ~/.bashrc lub równoważnym pliku:

export LD_LIBRARY_PATH=/usr/local/lib

lub

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

Użyj pierwszej formy, jeśli jest pusta (odpowiednik pustego ciągu lub w ogóle go nie ma), a drugiej, jeśli nie jest. Zwróć uwagę na wykorzystanie eksportu .

Vinay Sajip
źródło
2
Dzięki. Moja LD_LIBRARY_PATH nie została ustawiona, więc: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib Ale nadal otrzymuję ten sam błąd: $ python -c "import pycurl" Traceback (ostatnie wywołanie ostatnie): Plik „<string>”, wiersz 1, w <module> ImportError: libcurl.so.4: nie można otworzyć pliku obiektu współdzielonego: nie ma takiego pliku ani katalogu
2
Musiałem też dać mojemu użytkownikowi uprawnienia do czytania biblioteki po ustawieniu zmiennej LD_LIBRARY_PATH. Teraz w końcu działa.
José Ricardo
57

Upewnij się, że moduł libcurl.so znajduje się w ścieżce biblioteki systemowej, która jest odrębna i oddzielna od ścieżki biblioteki Pythona.

„Szybkim rozwiązaniem” jest dodanie tej ścieżki do zmiennej LD_LIBRARY_PATH. Jednak ustawienie tego systemu dla całego systemu (lub nawet konta) jest ZŁYM POMYSŁEM, ponieważ można to ustawić w taki sposób, że niektóre programy znajdą bibliotekę, której nie powinny, a co gorsza, otwierać luki w zabezpieczeniach.

Jeśli Twoje „biblioteki zainstalowane lokalnie” są zainstalowane na przykład w / usr / local / lib, dodaj ten katalog do /etc/ld.so.conf (jest to plik tekstowy) i uruchom „ldconfig”

Polecenie uruchomi narzędzie buforujące, ale utworzy również wszystkie niezbędne „dowiązania symboliczne” wymagane do działania systemu ładującego. Zaskakujące jest, że polecenie „make install” dla libcurl jeszcze tego nie zrobiło, ale możliwe, że nie mógł, gdyby / usr / local / lib nie znajdowało się już w /etc/ld.so.conf.

PS: możliwe, że plik /etc/ld.so.conf zawiera tylko „include ld.so.conf.d / *. Conf”. Nadal możesz dodać ścieżkę do katalogu po nim lub po prostu utworzyć nowy plik w katalogu, z którego jest dołączany. Nie zapomnij uruchomić po nim "ldconfig".

Bądź ostrożny. Złe popełnienie tego błędu może zepsuć system.

Dodatkowo: upewnij się, że Twój moduł Pythona jest skompilowany w TEJ wersji libcurl. Jeśli właśnie skopiowałeś jakieś pliki z innego systemu, to nie zawsze zadziała. W razie wątpliwości skompiluj swoje moduły w systemie, w którym zamierzasz je uruchomić.

Ch'marr
źródło
Dziękuję - to zadziałało. Zastanawiam się, dlaczego moja poprzednia próba „szybkiej naprawy” zmiany zmiennej LD_LIBRARY_PATH nie.
2
Zależy od wielu czynników. Oto jedna możliwość: twój kod był uruchamiany z apache lub cron. Programy te zazwyczaj „czyszczą” środowisko, więc musisz wykonać dodatkowe czynności, aby pobrać zmienne środowiskowe. Na przykład „SetEnv” w apache lub ustawienie zmiennej bezpośrednio w pliku crontab dla crona. Możliwości popełnienia błędów są nieograniczone!
Ch'marr
24

Możesz również ustawić LD_RUN_PATH na / usr / local / lib w swoim środowisku użytkownika podczas kompilowania pycurl w pierwszej kolejności. Spowoduje to osadzenie / usr / local / lib w atrybucie RPATH modułu rozszerzającego C, dzięki czemu automatycznie będzie wiedział, gdzie znaleźć bibliotekę w czasie wykonywania, bez konieczności ustawiania LD_LIBRARY_PATH w czasie wykonywania.

Graham Dumpleton
źródło
4
Alternatywnie, zastosowanie python setup.py build_ext --rpath=/usr/local/libprzy budowie modułu rozszerzenia piec w rpath
kynan
10

Miał dokładnie ten sam problem. Zainstalowałem curl 7.19 to / opt / curl /, aby upewnić się, że nie wpłynę na bieżące curl na naszych serwerach produkcyjnych. Po połączeniu libcurl.so.4 z / usr / lib:

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

Nadal mam ten sam błąd! Durf.

Ale uruchomienie ldconfig stworzyło powiązanie dla mnie i to zadziałało. W ogóle nie ma potrzeby ustawiania LD_RUN_PATH ani LD_LIBRARY_PATH. Wystarczy uruchomić ldconfig.

Matt
źródło
A jeśli nie mam uprawnień sudo? Nie mogę uruchomić ldconfig? Czy jest zatem sposób, aby usunąć powyższy błąd?
Prasanna,
2
@SPRajagopal: jeśli nie masz uprawnień do modyfikowania atrybutów systemu, musisz użyć LD_LIBRARY_PATHmetody zmiennej środowiskowej opisanej powyżej. Jeśli nie chcesz go ustawiać w swoim ~/.bashrc(dodawanie tego ustawienia nie jest dobrym pomysłem IMO), możesz napisać skrypt powłoki, który ustawia tę zmienną, a następnie uruchamia Pythona, a następnie wywołać ten skrypt.
MadScientist,
8

Jako uzupełnienie powyższych odpowiedzi - po prostu wpadam na podobny problem i pracuję całkowicie z domyślnie zainstalowanym Pythonem.

Kiedy wywołuję przykład udostępnionej biblioteki obiektów, której szukam LD_LIBRARY_PATH, otrzymuję coś takiego:

$ 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

Warto zauważyć, że nawet nie narzeka na import - narzeka na plik źródłowy!

Ale jeśli wymuszę załadowanie obiektu za pomocą 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

... od razu otrzymuję bardziej znaczący komunikat o błędzie - o brakującej zależności!

Pomyślałem, że zapiszę to tutaj - na zdrowie!

sdaau
źródło
Czy na pewno nie jest to nowy błąd, który pojawia się przed błędem OP?
David Knipe
1

Używam python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0i skompilowany plik .so znajduje się w folderze kompilacji. możesz wpisać, python setup.py --help build_extaby zobaczyć wyjaśnienia dotyczące -R i -I

ScutterKey
źródło
1

Dla mnie to, co tutaj działa, to użycie menedżera wersji, takiego jak pyenv , który zdecydowanie polecam, aby środowiska projektu i wersje pakietów były dobrze zarządzane i oddzielone od systemu operacyjnego.

Miałem ten sam błąd po aktualizacji systemu operacyjnego, ale został łatwo naprawiony w pyenv install 3.7-dev(używanej wersji).

elcortegano
źródło