Mengapa Python tidak dapat menemukan objek bersama yang ada dalam direktori di sys.path?

124

Saya mencoba mengimpor 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

Sekarang, libcurl.so.4masuk /usr/local/lib. Seperti yang Anda lihat, ini ada di 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']

Bantuan apa pun akan sangat dihargai.

BR123
sumber
Lihat jawaban saya yang diperbarui, jika Anda tidak mengatur LD_LIBRARY_PATHdengan benar (saya pikir komentar Anda memiliki titik dua yang hilang).
Vinay Sajip
1
Apakah ada symlink yang rusak di suatu tempat bernama libcurl.so.4? Sepertinya saya menemukan file tersebut tetapi tidak dapat membukanya. Jika semuanya gagal, serang penerjemah dan cari panggilan yang gagal.
Charles Duffy

Jawaban:

158

sys.pathhanya mencari modul Python. Untuk perpustakaan terkait dinamis, jalur yang dicari harus dalam LD_LIBRARY_PATH. Periksa apakah LD_LIBRARY_PATHtermasuk Anda /usr/local/lib, dan jika tidak, tambahkan dan coba lagi.

Beberapa informasi lebih lanjut ( sumber ):

Di Linux, variabel lingkungan LD_LIBRARY_PATH adalah kumpulan direktori yang dipisahkan oleh titik dua tempat perpustakaan harus dicari terlebih dahulu, sebelum kumpulan direktori standar; ini berguna saat men-debug pustaka baru atau menggunakan pustaka tidak standar untuk tujuan khusus. Variabel lingkungan LD_PRELOAD mencantumkan pustaka bersama dengan fungsi yang menggantikan set standar, seperti yang dilakukan /etc/ld.so.preload. Ini diimplementasikan oleh loader /lib/ld-linux.so. Saya harus mencatat bahwa, sementara LD_LIBRARY_PATH bekerja pada banyak sistem mirip Unix, itu tidak bekerja pada semua; misalnya, fungsi ini tersedia di HP-UX tetapi sebagai variabel lingkungan SHLIB_PATH, dan di AIX fungsi ini melalui variabel LIBPATH (dengan sintaks yang sama, daftar yang dipisahkan titik dua).

Perbarui: untuk menyetel LD_LIBRARY_PATH, gunakan salah satu dari yang berikut, idealnya di ~/.bashrc file Anda atau yang setara:

export LD_LIBRARY_PATH=/usr/local/lib

atau

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

Gunakan formulir pertama jika kosong (setara dengan string kosong, atau tidak ada sama sekali), dan formulir kedua jika tidak ada. Perhatikan penggunaan ekspor .

Vinay Sajip
sumber
2
Terima kasih. LD_LIBRARY_PATH saya tidak disetel, jadi: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib Tapi saya masih mendapatkan kesalahan yang sama: $ python -c "import pycurl" Traceback (panggilan terakhir terakhir): File "<string>", baris 1, di <module> ImportError: libcurl.so.4: tidak dapat membuka file objek bersama: Tidak ada file atau direktori seperti itu
2
Saya juga harus memberikan izin kepada pengguna saya untuk membaca perpustakaan setelah mengatur variabel LD_LIBRARY_PATH. Sekarang akhirnya berhasil.
José Ricardo
56

Pastikan modul libcurl.so Anda berada di jalur pustaka sistem, yang berbeda dan terpisah dari jalur pustaka python.

Sebuah "perbaikan cepat" adalah menambahkan jalur ini ke variabel LD_LIBRARY_PATH. Namun, menyetel lebar sistem (atau bahkan lebar akun) adalah IDE BURUK, karena dimungkinkan untuk menyetelnya sedemikian rupa sehingga beberapa program akan menemukan perpustakaan yang seharusnya tidak, atau bahkan lebih buruk, membuka lubang keamanan.

Jika "perpustakaan yang diinstal secara lokal" Anda diinstal di, misalnya, / usr / local / lib, tambahkan direktori ini ke /etc/ld.so.conf (ini adalah file teks) dan jalankan "ldconfig"

Perintah tersebut akan menjalankan utilitas caching, tetapi juga akan membuat semua "tautan simbolik" yang diperlukan agar sistem loader berfungsi. Mengejutkan bahwa "make install" untuk libcurl belum melakukan ini, tetapi mungkin saja tidak bisa jika / usr / local / lib belum ada di /etc/ld.so.conf.

NB: mungkin saja /etc/ld.so.conf Anda hanya berisi "include ld.so.conf.d / *. Conf". Anda masih dapat menambahkan jalur direktori setelahnya, atau cukup membuat file baru di dalam direktori tempat ia disertakan. Jangan lupa untuk menjalankan "ldconfig" setelahnya.

Hati-hati. Melakukan kesalahan ini dapat mengacaukan sistem Anda.

Selain itu: pastikan modul python Anda dikompilasi dengan versi libcurl ITU. Jika Anda baru saja menyalin beberapa file dari sistem lain, ini tidak akan selalu berhasil. Jika ragu, kompilasi modul Anda pada sistem tempat Anda ingin menjalankannya.

Ch'marr
sumber
Terima kasih - ini berhasil. Saya bertanya-tanya mengapa percobaan "perbaikan cepat" saya sebelumnya yang mengubah variabel LD_LIBRARY_PATH tidak berhasil.
2
Tergantung banyak faktor. Berikut satu kemungkinan: kode Anda dijalankan dari apache atau cron. Program-program tersebut biasanya "membersihkan" lingkungan, jadi Anda harus melakukan hal-hal tambahan untuk memasukkan variabel lingkungan. Misalnya, "SetEnv" di apache, atau menyetel variabel langsung di file crontab untuk cron. Kemungkinan kesalahan tidak terbatas!
Ch'marr
24

Anda juga dapat mengatur LD_RUN_PATH ke / usr / local / lib di lingkungan pengguna Anda saat Anda mengkompilasi pycurl di tempat pertama. Ini akan menyematkan / usr / local / lib dalam atribut RPATH dari modul ekstensi C. sehingga secara otomatis mengetahui di mana menemukan perpustakaan pada waktu proses tanpa harus menetapkan LD_LIBRARY_PATH pada waktu proses.

Graham Dumpleton
sumber
4
Alternatifnya, gunakan python setup.py build_ext --rpath=/usr/local/libsaat membangun modul ekstensi untuk memanggang di rpath
kynan
10

Punya masalah yang sama persis. Saya menginstal curl 7.19 ke / opt / curl / untuk memastikan bahwa saya tidak akan memengaruhi curl saat ini di server produksi kami. Setelah saya menautkan libcurl.so.4 ke / usr / lib:

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

Saya masih mendapat kesalahan yang sama! Durf.

Tetapi menjalankan ldconfig membuat tautan untuk saya dan itu berhasil. Tidak perlu menyetel LD_RUN_PATH atau LD_LIBRARY_PATH sama sekali. Hanya perlu menjalankan ldconfig.

Matt
sumber
Bagaimana jika saya tidak memiliki hak sudo? Saya tidak dapat menjalankan ldconfig? Apakah ada cara untuk menghapus kesalahan di atas?
Prasanna
2
@SPRajagopal: jika Anda tidak memiliki hak istimewa untuk mengubah atribut sistem, Anda harus menggunakan LD_LIBRARY_PATHmetode variabel lingkungan yang dijelaskan di atas. Jika Anda tidak ingin mengaturnya di ~/.bashrc(menambahkan pengaturan itu bukan ide yang baik IMO), Anda dapat menulis skrip shell yang menyetel variabel ini lalu menjalankan python, lalu memanggil skrip itu.
MadScientist
8

Sebagai suplemen untuk jawaban di atas - Saya baru saja mengalami masalah serupa, dan bekerja sepenuhnya dari python yang diinstal default.

Ketika saya memanggil contoh pustaka objek bersama yang saya cari LD_LIBRARY_PATH, saya mendapatkan sesuatu seperti ini:

$ 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

Khususnya, ia bahkan tidak mengeluh tentang impor - ia mengeluh tentang file sumber!

Tetapi jika saya memaksa pemuatan objek menggunakan 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

... Saya segera mendapatkan pesan kesalahan yang lebih berarti - tentang ketergantungan yang hilang!

Kupikir aku akan menuliskan ini di sini - cheers!

sdaau
sumber
Apakah Anda yakin itu bukan kesalahan baru yang terjadi sebelum kesalahan OP?
David Knipe
1

Saya menggunakan python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0dan file .so yang telah dikompilasi berada di bawah folder build. Anda bisa mengetik python setup.py --help build_extuntuk melihat penjelasan dari -R dan -I

ScutterKey
sumber
1

Bagi saya yang berhasil di sini adalah menggunakan pengelola versi seperti pyenv , yang sangat saya rekomendasikan agar lingkungan proyek dan versi paket Anda dikelola dengan baik dan terpisah dari sistem operasi.

Saya mengalami kesalahan yang sama setelah pembaruan OS, tetapi dengan mudah diperbaiki dengan pyenv install 3.7-dev(versi yang saya gunakan).

elcortegano.dll
sumber