Por que o Python não pode encontrar objetos compartilhados que estão nos diretórios no sys.path?


124

Estou tentando importar 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

Agora, libcurl.so.4está em /usr/local/lib. Como você pode ver, este é o seguinte 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']

Qualquer ajuda será muito apreciada.


Veja minha resposta atualizada, caso você não tenha definido LD_LIBRARY_PATHcorretamente (achei que seu comentário tinha dois pontos ausentes).
Vinay Sajip 08/07/2009

1
Existe um link simbólico quebrado em algum lugar chamado libcurl.so.4? Parece-me que está encontrando o arquivo, mas não é possível abri-lo. Se tudo mais falhar, procure o intérprete e procure a chamada que falhou.
Charles Duffy

Respostas:


158

sys.pathé pesquisado apenas para módulos Python. Para bibliotecas vinculadas dinâmicas, os caminhos pesquisados ​​devem estar LD_LIBRARY_PATH. Verifique se o seu LD_LIBRARY_PATHinclui /usr/local/libe, se não, adicione-o e tente novamente.

Mais algumas informações ( fonte ):

No Linux, a variável de ambiente LD_LIBRARY_PATH é um conjunto de diretórios separados por dois pontos, onde as bibliotecas devem ser pesquisadas primeiro, antes do conjunto padrão de diretórios; isso é útil ao depurar uma nova biblioteca ou ao usar uma biblioteca não padrão para fins especiais. A variável de ambiente LD_PRELOAD lista bibliotecas compartilhadas com funções que substituem o conjunto padrão, assim como o /etc/ld.so.preload. Eles são implementados pelo carregador /lib/ld-linux.so. Devo observar que, embora o LD_LIBRARY_PATH funcione em muitos sistemas semelhantes ao Unix, ele não funciona em todos; por exemplo, essa funcionalidade está disponível no HP-UX, mas como a variável de ambiente SHLIB_PATH, e no AIX essa funcionalidade é através da variável LIBPATH (com a mesma sintaxe, uma lista separada por dois pontos).

Atualização: para definir LD_LIBRARY_PATH, use um dos seguintes, idealmente no seu ~/.bashrc arquivo ou equivalente:

export LD_LIBRARY_PATH=/usr/local/lib

ou

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

Use o primeiro formulário, se estiver vazio (equivalente à string vazia, ou se não estiver presente), e o segundo formulário, se não estiver. Observe o uso de exportação .


2
Obrigado. Meu LD_LIBRARY_PATH não foi definido, portanto: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib Mas ainda recebo o mesmo erro: Traceback do $ python -c "import pycurl" (última chamada mais recente): File "<string>", linha 1, na <module> ImportError: libcurl.so.4: não pode abrir arquivo objeto compartilhado: Nenhum tal lima ou diretório

2
Eu também tive que dar permissões ao meu usuário para ler a biblioteca depois de definir a variável LD_LIBRARY_PATH. Agora finalmente funciona.
José Ricardo

56

Assegure-se de que seu módulo libcurl.so esteja no caminho da biblioteca do sistema, que é distinto e separado do caminho da biblioteca python.

Uma "solução rápida" é adicionar esse caminho a uma variável LD_LIBRARY_PATH. No entanto, definir esse sistema como um todo (ou mesmo para toda a conta) é uma BAD IDEA, pois é possível configurá-lo de tal maneira que alguns programas encontrarão uma biblioteca que não deve, ou pior ainda, abrir brechas na segurança.

Se suas "bibliotecas instaladas localmente" estiverem instaladas em, por exemplo, / usr / local / lib, inclua este diretório em /etc/ld.so.conf (é um arquivo de texto) e execute "ldconfig"

O comando executará um utilitário de armazenamento em cache, mas também criará todos os "links simbólicos" necessários para o funcionamento do sistema do carregador. É surpreendente que o "make install" do libcurl ainda não tenha feito isso, mas é possível que não seja possível se o / usr / local / lib já não estiver no /etc/ld.so.conf.

PS: é possível que o seu /etc/ld.so.conf contenha nada além de "inclua ld.so.conf.d / *. Conf". Você ainda pode adicionar um caminho de diretório após ele ou apenas criar um novo arquivo dentro do diretório do qual está sendo incluído. Não se esqueça de executar o "ldconfig" depois dele.

Seja cuidadoso. Entender isso errado pode estragar o seu sistema.

Além disso: verifique se o seu módulo python está compilado com a versão da libcurl. Se você acabou de copiar alguns arquivos de outro sistema, isso nem sempre funciona. Em caso de dúvida, compile seus módulos no sistema em que você deseja executá-los.


Obrigado - isso funcionou. Gostaria de saber por que minha tentativa rápida de "correção rápida" alterando a variável LD_LIBRARY_PATH não foi.

2
Depende de muitos fatores. Aqui está uma possibilidade: seu código estava sendo executado no apache ou cron. Esses programas normalmente "limpam" o ambiente, então você precisa fazer coisas extras para obter variáveis ​​de ambiente. Por exemplo, "SetEnv" no apache ou definir a variável no arquivo crontab do cron. As possibilidades de erros são infinitas!
Ch'marr 03/09/09

24

Você também pode definir LD_RUN_PATH como / usr / local / lib em seu ambiente de usuário quando compilar pycurl em primeiro lugar. Isso incorporará / usr / local / lib no atributo RPATH do módulo de extensão C. Para que ele saiba automaticamente onde encontrar a biblioteca no tempo de execução sem ter que LD_LIBRARY_PATH definido no tempo de execução.


4
Alternativamente, o uso python setup.py build_ext --rpath=/usr/local/libna construção do módulo de extensão para assar no rpath
Kynan

10

Tinha exatamente o mesmo problema. Instalei o curl 7.19 em / opt / curl / para garantir que não afetaria o curl atual nos nossos servidores de produção. Depois que vinculei o libcurl.so.4 ao / usr / lib:

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

Eu ainda tenho o mesmo erro! Durf.

Mas rodar o ldconfig faz a ligação para mim e isso funcionou. Não há necessidade de definir o LD_RUN_PATH ou LD_LIBRARY_PATH. Só precisava executar o ldconfig.


E se eu não tiver privilégio de sudo? Não consigo executar o ldconfig? Existe alguma maneira de limpar o erro acima então?
Prasanna

2
@SPRajagopal: se você não possui privilégios para modificar os atributos do sistema, deve usar o LD_LIBRARY_PATHmétodo da variável de ambiente descrito acima. Se você não deseja defini-lo no seu ~/.bashrc(adicionar essa configuração não é uma boa ideia para IMO), você pode escrever um script de shell que defina essa variável e, em seguida, execute python, e chame esse script.
Cientista louco

8

Como um complemento às respostas acima - estou apenas encontrando um problema semelhante e trabalhando completamente com o python padrão instalado.

Quando eu chamo o exemplo da biblioteca de objetos compartilhados que estou procurando LD_LIBRARY_PATH, recebo algo assim:

$ 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

Notavelmente, ele nem reclama da importação - reclama do arquivo de origem!

Mas se eu forçar o carregamento do objeto usando 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

... Recebo imediatamente uma mensagem de erro mais significativa - sobre uma falta de dependência!

Só pensei em anotar isso aqui - saúde!


Tem certeza de que não é um novo erro que está ocorrendo antes do erro do OP?
David Knipe 23/02

1

Eu uso python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0e o arquivo .so compilado está na pasta build. você pode digitar python setup.py --help build_extpara ver as explicações de -R e -I


1

Para mim, o que funciona aqui é usar um gerenciador de versões como o pyenv , que eu recomendo fortemente que seus ambientes de projeto e versões de pacotes sejam bem gerenciados e separados do sistema operacional.

Eu tive esse mesmo erro após uma atualização do sistema operacional, mas foi facilmente corrigido com pyenv install 3.7-dev(a versão que eu uso).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.