Tại sao Python không thể tìm thấy các đối tượng được chia sẻ trong thư mục trong sys.path?


124

Tôi đang cố nhập 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

Bây giờ, libcurl.so.4là trong /usr/local/lib. Như bạn có thể thấy, đây là trong 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']

Chúng tôi rất trân trọng bất kỳ sự giúp đỡ nào.


Xem câu trả lời cập nhật của tôi, trong trường hợp bạn đặt không LD_LIBRARY_PATHchính xác (tôi nghĩ rằng nhận xét của bạn bị thiếu dấu hai chấm).
Vinay Sajip

1
Có một liên kết tượng trưng bị hỏng ở đâu đó có tên libcurl.so.4 không? Đối với tôi, có vẻ như nó đang tìm thấy tệp nhưng không thể mở được. Nếu vẫn thất bại, hãy tìm thông dịch viên và tìm kiếm cuộc gọi thất bại.
Charles Duffy

Câu trả lời:


158

sys.pathchỉ được tìm kiếm cho các mô-đun Python. Đối với các thư viện được liên kết động, các đường dẫn được tìm kiếm phải ở trong LD_LIBRARY_PATH. Kiểm tra xem bạn LD_LIBRARY_PATHcó bao gồm không /usr/local/libvà nếu không, hãy thêm và thử lại.

Một số thông tin khác ( nguồn ):

Trong Linux, biến môi trường LD_LIBRARY_PATH là một tập hợp thư mục được phân tách bằng dấu hai chấm, nơi các thư viện sẽ được tìm kiếm đầu tiên, trước tập thư mục chuẩn; điều này rất hữu ích khi gỡ lỗi một thư viện mới hoặc sử dụng một thư viện không chuẩn cho các mục đích đặc biệt. Biến môi trường LD_PRELOAD liệt kê các thư viện được chia sẻ với các hàm ghi đè bộ tiêu chuẩn, giống như /etc/ld.so.preload. Chúng được thực thi bởi trình tải /lib/ld-linux.so. Tôi nên lưu ý rằng, mặc dù LD_LIBRARY_PATH hoạt động trên nhiều hệ thống giống Unix, nhưng nó không hoạt động trên tất cả; ví dụ: chức năng này khả dụng trên HP-UX nhưng là biến môi trường SHLIB_PATH và trên AIX, chức năng này thông qua biến LIBPATH (với cùng một cú pháp, danh sách được phân tách bằng dấu hai chấm).

Cập nhật: để đặt LD_LIBRARY_PATH, hãy sử dụng một trong các cách sau, lý tưởng nhất là trong ~/.bashrc tệp của bạn hoặc tệp tương đương:

export LD_LIBRARY_PATH=/usr/local/lib

hoặc là

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

Sử dụng biểu mẫu đầu tiên nếu nó trống (tương đương với chuỗi trống hoặc hoàn toàn không có) và biểu mẫu thứ hai nếu không. Lưu ý việc sử dụng xuất khẩu .


2
Cảm ơn. LD_LIBRARY_PATH của tôi chưa được đặt, vì vậy: $ LD_LIBRARY_PATH = / usr / local / lib $ LD_LIBRARY_PATH / usr / local / lib Nhưng tôi vẫn gặp lỗi tương tự: $ python -c "import pycurl" Traceback (lần gọi gần đây nhất): Tệp "<string>", dòng 1, trong <module> ImportError: libcurl.so.4: không thể mở tệp đối tượng được chia sẻ: Không có tệp hoặc thư mục như vậy

2
Tôi cũng phải cấp quyền cho người dùng của mình để đọc thư viện sau khi đặt biến LD_LIBRARY_PATH. Bây giờ nó cuối cùng đã hoạt động.
José Ricardo,

56

Đảm bảo mô-đun libcurl.so của bạn nằm trong đường dẫn thư viện hệ thống, đường dẫn này riêng biệt và tách biệt với đường dẫn thư viện python.

Cách "khắc phục nhanh" là thêm đường dẫn này vào biến LD_LIBRARY_PATH. Tuy nhiên, việc đặt hệ thống đó trên toàn bộ hệ thống (hoặc thậm chí là toàn bộ tài khoản) là một Ý TƯỞNG XẤU, vì có thể đặt nó theo cách mà một số chương trình sẽ tìm thấy một thư viện mà nó không nên, hoặc thậm chí tệ hơn, mở ra các lỗ hổng bảo mật.

Nếu "thư viện được cài đặt cục bộ" của bạn được cài đặt, chẳng hạn như / usr / local / lib, hãy thêm thư mục này vào /etc/ld.so.conf (đó là một tệp văn bản) và chạy "ldconfig"

Lệnh sẽ chạy một tiện ích bộ nhớ đệm, nhưng cũng sẽ tạo tất cả các "liên kết tượng trưng" cần thiết để hệ thống trình nạp hoạt động. Điều đáng ngạc nhiên là "thực hiện cài đặt" cho libcurl đã không làm được điều này, nhưng có thể không thực hiện được nếu / usr / local / lib chưa có trong /etc/ld.so.conf.

Tái bút: có thể là /etc/ld.so.conf của bạn không chứa gì ngoài "include ld.so.conf.d / *. Conf". Bạn vẫn có thể thêm một đường dẫn thư mục sau nó hoặc chỉ cần tạo một tệp mới bên trong thư mục mà nó đang được đưa vào. Đừng quên chạy "ldconfig" sau nó.

Hãy cẩn thận. Làm sai điều này có thể làm hỏng hệ thống của bạn.

Ngoài ra: hãy đảm bảo rằng mô-đun python của bạn được biên dịch dựa trên phiên bản RẰNG của libcurl. Nếu bạn vừa sao chép một số tệp từ một hệ thống khác, điều này sẽ không luôn hoạt động. Nếu nghi ngờ, hãy biên dịch các mô-đun của bạn trên hệ thống mà bạn định chạy chúng.


Cảm ơn bạn - điều này đã hiệu quả. Tôi tự hỏi tại sao trước đây tôi đã cố gắng "sửa chữa nhanh" thay đổi biến LD_LIBRARY_PATH.

2
Phụ thuộc vào rất nhiều yếu tố. Đây là một khả năng: mã của bạn đang được chạy từ apache hoặc cron. Các chương trình đó thường "làm sạch" môi trường, vì vậy bạn phải thực hiện thêm nhiều thứ để đưa các biến môi trường vào. Ví dụ: "SetEnv" trong apache hoặc đặt biến ngay trong tệp crontab cho cron. Khả năng mắc sai lầm là vô tận!
Ch'marr

24

Bạn cũng có thể đặt LD_RUN_PATH thành / usr / local / lib trong môi trường người dùng của mình khi bạn biên dịch pycurl ngay từ đầu. Thao tác này sẽ nhúng / usr / local / lib vào thuộc tính RPATH của mô-đun mở rộng C. Do đó, nó sẽ tự động biết nơi tìm thư viện tại thời điểm chạy mà không cần phải đặt LD_LIBRARY_PATH tại thời điểm chạy.


4
Ngoài ra, sử dụng python setup.py build_ext --rpath=/usr/local/libkhi xây dựng mô-đun mở rộng để nướng trong rpath
kynan

10

Có cùng một vấn đề. Tôi đã cài đặt curl 7.19 thành / opt / curl / để đảm bảo rằng tôi sẽ không ảnh hưởng đến curl hiện tại trên máy chủ sản xuất của chúng tôi. Sau khi tôi liên kết libcurl.so.4 với / usr / lib:

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

Tôi vẫn gặp lỗi tương tự! Lướt ván.

Nhưng chạy ldconfig tạo liên kết cho tôi và điều đó đã hoạt động. Không cần đặt LD_RUN_PATH hoặc LD_LIBRARY_PATH. Chỉ cần thiết để chạy ldconfig.


Nếu tôi không có đặc quyền sudo thì sao? Tôi không thể chạy ldconfig? Có cách nào để xóa lỗi trên sau đó không?
Prasanna

2
@SPRajagopal: nếu bạn không có đặc quyền sửa đổi các thuộc tính hệ thống, bạn phải sử dụng LD_LIBRARY_PATHphương thức biến môi trường được mô tả ở trên. Nếu bạn không muốn đặt nó trong của bạn ~/.bashrc(thêm cài đặt đó không phải là ý kiến ​​hay của IMO), bạn có thể viết một tập lệnh shell đặt biến này rồi chạy python, sau đó gọi tập lệnh đó.
MadScientist

8

Như một phần bổ sung cho các câu trả lời ở trên - tôi vừa gặp phải một vấn đề tương tự và đang hoạt động hoàn toàn với python được cài đặt mặc định.

Khi tôi gọi ví dụ về thư viện đối tượng được chia sẻ mà tôi đang tìm kiếm LD_LIBRARY_PATH, tôi nhận được một cái gì đó như sau:

$ 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

Đáng chú ý, nó thậm chí không phàn nàn về việc nhập - nó phàn nàn về tệp nguồn!

Nhưng nếu tôi buộc tải đối tượng bằng cách sử dụng 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

... Tôi ngay lập tức nhận được một thông báo lỗi có ý nghĩa hơn - về việc thiếu phụ thuộc!

Tôi chỉ nghĩ rằng tôi sẽ ghi lại điều này ở đây - chúc mừng!


Bạn có chắc đó không phải là lỗi mới xảy ra trước lỗi của OP?
David Knipe

1

Tôi sử dụng python setup.py build_ext -R/usr/local/lib -I/usr/local/include/libcalg-1.0và tệp .so đã biên dịch nằm trong thư mục xây dựng. bạn có thể nhập python setup.py --help build_extđể xem giải thích của -R và -I


1

Đối với tôi, điều hoạt động ở đây là sử dụng trình quản lý phiên bản như pyenv , điều này tôi thực sự khuyên bạn nên quản lý tốt các môi trường dự án và phiên bản gói của bạn và tách biệt khỏi hệ thống hoạt động.

Tôi đã gặp lỗi tương tự sau khi cập nhật hệ điều hành, nhưng đã được khắc phục dễ dàng với pyenv install 3.7-dev(phiên bản tôi sử dụng).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.