Perché Python non riesce a trovare oggetti condivisi che si trovano nelle directory in sys.path?


124

Sto cercando di importare 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

Ora libcurl.so.4è dentro /usr/local/lib. Come puoi vedere, questo è 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']

Qualsiasi aiuto sarà molto apprezzato.


Vedi la mia risposta aggiornata, nel caso in cui non l'hai impostata LD_LIBRARY_PATHcorrettamente (pensavo che il tuo commento avesse i due punti mancanti).
Vinay Sajip

1
C'è un collegamento simbolico rotto da qualche parte chiamato libcurl.so.4? Mi sembra che stia trovando il file ma non sia in grado di aprirlo. Se tutto il resto fallisce, strace l'interprete e cerca la chiamata fallita.
Charles Duffy

Risposte:


158

sys.pathviene cercato solo per i moduli Python. Per le librerie collegate dinamiche, i percorsi cercati devono essere in LD_LIBRARY_PATH. Controlla se LD_LIBRARY_PATHinclude /usr/local/libe, in caso contrario, aggiungilo e riprova.

Qualche informazione in più ( fonte ):

In Linux, la variabile d'ambiente LD_LIBRARY_PATH è un insieme di directory separate da due punti in cui le librerie dovrebbero essere cercate prima, prima dell'insieme standard di directory; questo è utile quando si esegue il debug di una nuova libreria o si utilizza una libreria non standard per scopi speciali. La variabile d'ambiente LD_PRELOAD elenca le librerie condivise con funzioni che sovrascrivono l'insieme standard, proprio come fa /etc/ld.so.preload. Questi sono implementati dal loader /lib/ld-linux.so. Dovrei notare che, mentre LD_LIBRARY_PATH funziona su molti sistemi simili a Unix, non funziona su tutti; ad esempio, questa funzionalità è disponibile su HP-UX ma come variabile d'ambiente SHLIB_PATH e su AIX questa funzionalità è tramite la variabile LIBPATH (con la stessa sintassi, un elenco separato da due punti).

Aggiorna: per impostare LD_LIBRARY_PATH, usa uno dei seguenti, idealmente nel tuo ~/.bashrc file o equivalente:

export LD_LIBRARY_PATH=/usr/local/lib

o

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

Usa il primo modulo se è vuoto (equivalente alla stringa vuota, o non è affatto presente) e il secondo modulo se non lo è. Nota l'uso dell'esportazione .


2
Grazie. Il mio LD_LIBRARY_PATH non è stato impostato, quindi: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib Ma ricevo ancora lo stesso errore: $ python -c "import pycurl" Traceback (la chiamata più recente per ultima): File "<stringa>", riga 1, in <module> ImportError: libcurl.so.4: impossibile aprire il file oggetto condiviso: nessun file o directory di questo tipo

2
Ho anche dovuto dare i permessi al mio utente per leggere la libreria dopo aver impostato la variabile LD_LIBRARY_PATH. Ora finalmente funziona.
José Ricardo

56

Assicurati che il tuo modulo libcurl.so sia nel percorso della libreria di sistema, che è distinto e separato dal percorso della libreria python.

Una "soluzione rapida" consiste nell'aggiungere questo percorso a una variabile LD_LIBRARY_PATH. Tuttavia, impostare tale sistema a livello di sistema (o anche a livello di account) è una CATTIVA IDEA, poiché è possibile impostarlo in modo tale che alcuni programmi trovino una libreria che non dovrebbe, o peggio ancora, aprire falle di sicurezza.

Se le tue "librerie installate localmente" sono installate, ad esempio, in / usr / local / lib, aggiungi questa directory a /etc/ld.so.conf (è un file di testo) ed esegui "ldconfig"

Il comando eseguirà un'utilità di memorizzazione nella cache, ma creerà anche tutti i "collegamenti simbolici" necessari per il funzionamento del sistema di caricamento. È sorprendente che "make install" per libcurl non lo abbia già fatto, ma è possibile che non sia così se / usr / local / lib non è già in /etc/ld.so.conf.

PS: è possibile che il tuo /etc/ld.so.conf non contenga altro che "include ld.so.conf.d / *. Conf". È ancora possibile aggiungere un percorso di directory dopo di esso o semplicemente creare un nuovo file all'interno della directory da cui viene incluso. Non dimenticare di eseguire "ldconfig" dopo di esso.

Stai attento. Sbagliare può rovinare il tuo sistema.

Inoltre: assicurati che il tuo modulo python sia compilato con QUELLA versione di libcurl. Se hai appena copiato alcuni file da un altro sistema, questo non funzionerà sempre. In caso di dubbio, compilare i moduli sul sistema su cui si intende eseguirli.


Grazie - ha funzionato. Mi chiedo perché la mia "soluzione rapida" precedentemente tentata di modificare la variabile LD_LIBRARY_PATH non lo abbia fatto.

2
Dipende da molti fattori. Ecco una possibilità: il tuo codice veniva eseguito da apache o cron. Quei programmi tipicamente "ripuliscono" l'ambiente, quindi devi fare cose extra per ottenere le variabili di ambiente. Ad esempio, "SetEnv" in apache, o impostare la variabile direttamente nel file crontab per cron. Le possibilità di errore sono infinite!
Ch'marr

24

Puoi anche impostare LD_RUN_PATH su / usr / local / lib nel tuo ambiente utente quando compili pycurl in primo luogo. Questo incorporerà / usr / local / lib nell'attributo RPATH del modulo di estensione C.so in modo che sappia automaticamente dove trovare la libreria in fase di esecuzione senza dover impostare LD_LIBRARY_PATH in fase di esecuzione.


4
In alternativa, utilizzare python setup.py build_ext --rpath=/usr/local/libdurante la creazione del modulo di estensione per eseguire il bake nel rpath
kynan

10

Ha avuto lo stesso identico problema. Ho installato curl 7.19 su / opt / curl / per assicurarmi di non influire sull'attuale curl sui nostri server di produzione. Dopo aver collegato libcurl.so.4 a / usr / lib:

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

Ho ancora lo stesso errore! Durf.

Ma l'esecuzione di ldconfig ha creato il collegamento per me e ha funzionato. Non è affatto necessario impostare LD_RUN_PATH o LD_LIBRARY_PATH. Avevo solo bisogno di eseguire ldconfig.


E se non ho il privilegio sudo? Non riesco a eseguire ldconfig? C'è un modo per cancellare l'errore di cui sopra allora?
Prasanna

2
@SPRajagopal: se non hai i privilegi per modificare gli attributi di sistema devi usare il LD_LIBRARY_PATHmetodo della variabile d'ambiente descritto sopra. Se non vuoi impostarlo nel tuo ~/.bashrc(aggiungere quell'impostazione non è una buona idea IMO) puoi scrivere uno script di shell che imposta questa variabile, quindi esegue python, quindi chiama quello script.
MadScientist

8

Come supplemento alle risposte precedenti, mi sto imbattendo in un problema simile e sto lavorando completamente con il python installato di default.

Quando chiamo l'esempio della libreria di oggetti condivisi con cui cerco LD_LIBRARY_PATH, ottengo qualcosa del genere:

$ 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

In particolare, non si lamenta nemmeno dell'importazione - si lamenta del file sorgente!

Ma se forzo il caricamento dell'oggetto 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

... Ricevo immediatamente un messaggio di errore più significativo - su una dipendenza mancante!

Ho solo pensato di annotarlo qui - applausi!


Sei sicuro che non sia un nuovo errore che si sta verificando prima dell'errore di OP?
David Knipe,

1

Io uso python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0e il file .so compilato si trova nella cartella build. puoi digitare python setup.py --help build_extper vedere le spiegazioni di -R e -I


1

Per me ciò che funziona qui è utilizzare un gestore di versioni come pyenv , che consiglio vivamente per ottenere gli ambienti del progetto e le versioni dei pacchetti ben gestiti e separati da quelli del sistema operativo.

Ho riscontrato lo stesso errore dopo un aggiornamento del sistema operativo, ma è stato facilmente risolto con pyenv install 3.7-dev(la versione che utilizzo).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.