Чому Python не може знайти спільні об’єкти, що знаходяться в каталогах на sys.path?


124

Я намагаюся імпортувати 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

Тепер, libcurl.so.4в /usr/local/lib. Як бачите, це в 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']

Будь-яка допомога буде дуже вдячна.


Дивіться мою оновлену відповідь, якщо ви неправильно встановили LD_LIBRARY_PATH(я вважав, що у вашому коментарі відсутня двокрапка).
Vinay Sajip

1
Чи є зламане символьне посилання десь з назвою libcurl.so.4? Мені здається, що він знаходить файл, але не може його відкрити. Якщо все інше виходить з ладу, напружте перекладача та шукайте невдалий дзвінок.
Чарльз Даффі

Відповіді:


158

sys.pathшукається лише для модулів Python. Для динамічно пов'язаних бібліотек потрібні шляхи пошуку LD_LIBRARY_PATH. Перевірте, чи LD_LIBRARY_PATHмістить ваш текст /usr/local/lib, а якщо це не так, додайте його та спробуйте ще раз.

Ще трохи інформації ( джерело ):

В Linux змінна середовища LD_LIBRARY_PATH - це розділений двокрапкою набір каталогів, де слід шукати бібліотеки спочатку перед стандартним набором каталогів; це корисно при налагодженні нової бібліотеки або використанні нестандартної бібліотеки для спеціальних цілей. Змінна середовища LD_PRELOAD перераховує спільні бібліотеки з функціями, які перекривають стандартний набір, як і /etc/ld.so.preload. Вони реалізовані завантажувачем /lib/ld-linux.so. Зазначу, що, хоча LD_LIBRARY_PATH працює на багатьох системах, схожих на Unix, він працює не на всіх; Наприклад, ця функціональність доступна в HP-UX, але як змінна середовище SHLIB_PATH, а в AIX ця функціональність здійснюється через змінну LIBPATH (з тим же синтаксисом, розділеним двокрапкою).

Оновлення: щоб встановити LD_LIBRARY_PATH, використовуйте одне із наведених нижче, в ідеалі у вашому ~/.bashrc або еквівалентному файлі:

export LD_LIBRARY_PATH=/usr/local/lib

або

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

Використовуйте першу форму, якщо вона порожня (еквівалентна порожній рядку або зовсім не присутня), а другу форму, якщо її немає. Зауважте використання експорту .


2
Дякую. Мій LD_LIBRARY_PATH не встановлено, тому: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib Але я все одно отримую ту саму помилку: $ python -c "імпортувати pycurl" Traceback (останній дзвінок останній): Файл "<string>", рядок 1, в <module> ImportError: libcurl.so.4: не вдається відкрити спільний файл об'єкта: такого файлу чи каталогу немає

2
Я також повинен був дати дозволу моєму користувачеві читати бібліотеку після встановлення змінної LD_LIBRARY_PATH. Тепер це нарешті працює.
Хосе Рікардо

56

Переконайтесь, що ваш модуль libcurl.so знаходиться в шлях до системної бібліотеки, який відрізняється від шляху бібліотеки python.

"Швидке виправлення" - це додати цей шлях до змінної LD_LIBRARY_PATH. Однак якщо встановити цю систему (або навіть ширину облікового запису), це BAD IDEA, оскільки можна встановити її таким чином, що деякі програми знайдуть бібліотеку, в якій вона не повинна або, що ще гірше, не відкриє отвори в безпеці.

Якщо ваші "локально встановлені бібліотеки" встановлені, наприклад, / usr / local / lib, додайте цей каталог у /etc/ld.so.conf (це текстовий файл) та запустіть "ldconfig"

Команда запустить утиліту кешування, але також створить усі необхідні "символічні посилання", необхідні для роботи системи завантажувача. Дивно, що "make install" для libcurl цього не робилося, але можливо, це не могло, якщо / usr / local / lib вже не в /etc/ld.so.conf.

PS: можливо, що ваш /etc/ld.so.conf не містить нічого, крім "включати ld.so.conf.d / *. Conf". Ви можете додати шлях до каталогу до нього або просто створити новий файл всередині каталогу, з якого він включений. Не забудьте запустити "ldconfig" після нього.

Будь обережний. Помилка цієї помилки може накрутити вашу систему.

Додатково: переконайтеся, що ваш модуль python складений із ТОЇ версії libcurl. Якщо ви просто скопіювали деякі файли з іншої системи, це звичайно завжди працює. Якщо ви сумніваєтесь, компілюйте свої модулі в системі, на якій ви маєте намір запустити їх.


Дякую - це спрацювало. Цікаво, чому мої раніше спроби "швидкого виправлення" зміни змінної LD_LIBRARY_PATH не зробили.

2
Залежить від безлічі факторів. Ось одна з можливостей: ваш код запускався з apache або cron. Ці програми, як правило, "очищають" середовище, тому вам доведеться зайвий матеріал, щоб отримати змінні середовища. Наприклад, "SetEnv" в апачі або встановити зміну право у файлі crontab для cron. Можливості помилок безмежні!
Ch'marr

24

Ви також можете встановити LD_RUN_PATH в / usr / local / lib у вашому користувальницькому середовищі, коли ви компілюєте pycurl в першу чергу. Це вбудує / usr / local / lib в атрибут RPATH модуля розширення C. Таким чином, щоб він автоматично знав, де знайти бібліотеку під час виконання без встановлення LD_LIBRARY_PATH на час виконання.


4
Як варіант, використовуйте python setup.py build_ext --rpath=/usr/local/libпри складанні модуля розширення, щоб запікати на rpath
kynan

10

Був точно такий самий випуск. Я встановив curl 7.19 в / opt / curl /, щоб переконатися, що я не вплинув на поточну завивку на наших виробничих серверах. Одного разу я зв’язав libcurl.so.4 з / usr / lib:

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

Я все-таки отримав ту ж помилку! Дурф.

Але запуск ldconfig зробить зв’язок для мене, і це спрацювало. Не потрібно встановлювати LD_RUN_PATH або LD_LIBRARY_PATH взагалі. Просто потрібно запустити ldconfig.


Що робити, якщо я не маю привілею судо? Я не можу запустити ldconfig? Чи є тоді спосіб очистити вищевказану помилку?
Прасанна

2
@SPRajagopal: якщо у вас немає привілеїв для зміни системних атрибутів, ви повинні використовувати LD_LIBRARY_PATH метод змінної середовища, описаний вище. Якщо ви не хочете встановлювати його у своєму ~/.bashrc(додавши, що налаштування не є гарною ідеєю IMO), ви можете написати скрипт оболонки, який встановлює цю змінну, а потім запустить python, а потім викликати цей скрипт.
MadScientist

8

Як доповнення до вищезазначених відповідей - я просто натрапляю на подібну проблему і працюю повністю над встановленим за замовчуванням python.

Коли я називаю приклад бібліотеки спільних об'єктів, яку я шукаю LD_LIBRARY_PATH, я отримую щось подібне:

$ 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

Зокрема, він навіть не скаржиться на імпорт - він скаржиться на вихідний файл!

Але якщо я змушую завантажувати об'єкт за допомогою 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

... Я одразу отримую більш змістовне повідомлення про помилку - про відсутність залежності!

Я просто подумав, що я тут це зафіксую - ура!


Ви впевнені, що це не нова помилка, яка сталася до помилки ОП?
Девід Найпе

1

Я використовую, python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0і компільований .so файл знаходиться в папці збірки. ви можете ввести, python setup.py --help build_extщоб побачити пояснення -R і -I


1

Для мене тут працює використання диспетчера версій, такого як pyenv , який я настійно рекомендую добре керувати вашими середовищами проектів та версіями пакетів та відокремлюватись від операційної системи.

У мене була така сама помилка після оновлення ОС, але її легко виправити pyenv install 3.7-dev(використовувана версія).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.