Почему Python не может найти общие объекты, которые находятся в каталогах в sys.path?

125

Я пытаюсь импортировать 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']

Любая помощь будет оценена.

BR123
источник
См. Мой обновленный ответ, если вы установили LD_LIBRARY_PATHнеправильно (я думал, в вашем комментарии отсутствует двоеточие).
Vinay Sajip 08
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 "import pycurl" Traceback (последний вызов последнего): файл «<string>», строка 1, в <module> ImportError: libcurl.so.4: невозможно открыть файл общих объектов: нет такого файла или каталога
2
Мне также пришлось предоставить моему пользователю разрешение на чтение библиотеки после установки переменной LD_LIBRARY_PATH. Теперь это наконец работает.
Хосе Рикардо
57

Убедитесь, что ваш модуль libcurl.so находится в пути к системной библиотеке, который отличается и отличается от пути к библиотеке python.

«Быстрое исправление» - добавить этот путь к переменной LD_LIBRARY_PATH. Однако установка этой системы (или даже учетной записи) является ПЛОХОЙ ИДЕЕЙ, поскольку ее можно настроить таким образом, чтобы некоторые программы находили библиотеку, которой она не должна, или, что еще хуже, открывать дыры в безопасности.

Если ваши «локально установленные библиотеки» установлены, например, в / usr / local / lib, добавьте этот каталог в /etc/ld.so.conf (это текстовый файл) и запустите «ldconfig»

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

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

Быть осторожен. Неправильный ответ может испортить вашу систему.

Дополнительно: убедитесь, что ваш модуль python скомпилирован с ЭТОЙ версией libcurl. Если вы просто скопировали некоторые файлы из другой системы, это не всегда сработает. В случае сомнений скомпилируйте свои модули в системе, в которой вы собираетесь их запускать.

Ch'marr
источник
Спасибо, это сработало. Интересно, почему моя предыдущая попытка «быстрого исправления» с изменением переменной LD_LIBRARY_PATH не сделала этого.
2
Зависит от множества факторов. Вот одна возможность: ваш код запускался из apache или cron. Эти программы обычно «очищают» среду, поэтому вам нужно делать дополнительные вещи, чтобы получить переменные среды. Например, «SetEnv» в apache или установка переменной прямо в файле crontab для cron. Возможности для ошибок безграничны!
Ch'marr 03
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при создании модуля расширения для запекания
kynan
10

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

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

У меня все еще та же ошибка! Durf.

Но запуск ldconfig сделал для меня связь, и это сработало. Нет необходимости устанавливать LD_RUN_PATH или LD_LIBRARY_PATH вообще. Просто нужно было запустить ldconfig.

Matt
источник
Что делать, если у меня нет привилегии sudo? Я не могу запустить ldconfig? Есть ли способ устранить указанную выше ошибку?
Prasanna
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

... Я сразу получаю более значимое сообщение об ошибке - об отсутствующей зависимости!

Просто подумал, что запишу это здесь - ура!

sdaau
источник
Вы уверены, что это не новая ошибка, которая возникает до ошибки OP?
Дэвид Книп
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

ScutterKey
источник
1

Для меня здесь работает диспетчер версий, такой как pyenv , который я настоятельно рекомендую, чтобы ваши среды проекта и версии пакетов хорошо управлялись и были отделены от операционной системы.

У меня была такая же ошибка после обновления ОС, но она была легко исправлена pyenv install 3.7-dev(той версией, которую я использую).

elcortegano
источник