2009-05-13 25 views
29

Làm cách nào để bạn cập nhật biến môi trường này khi chạy để các ctype có thể tải thư viện ở bất kỳ đâu? Tôi đã thử những điều sau đây và dường như không hoạt động.Thay đổi LD_LIBRARY_PATH lúc chạy cho ctypes

from ctypes import * 
os.environ['LD_LIBRARY_PATH'] = "/home/starlon/Projects/pyCFA635/lib" 
os.putenv('LD_LIBRARY_PATH', "/home/starlon/Projects/pyCFA635/lib") 
lib = CDLL("libevaluator.so") 

Trả lời

35

Vào thời điểm một chương trình như Python đang chạy, bộ nạp động (ld.so.1 hoặc một cái gì đó tương tự) đã đọc LD_LIBRARY_PATH và sẽ không nhận thấy bất kỳ thay đổi sau đó. Vì vậy, trừ khi phần mềm Python tự đánh giá LD_LIBRARY_PATH và sử dụng nó để xây dựng tên đường dẫn có thể có của thư viện cho dlopen() hoặc một hàm tương đương để sử dụng, việc đặt biến trong tập lệnh sẽ không có hiệu lực.

Giả sử bạn nói nó không hoạt động, có vẻ hợp lý khi giả sử rằng Python không xây dựng và thử tất cả các tên thư viện có thể; nó có thể dựa vào LD_LIBRARY_PATH một mình.

+5

điều này chẩn đoán sự cố nhưng không giải quyết được. – dbliss

13

CDLL có thể được chuyển một tên đường dẫn đủ điều kiện, vì vậy ví dụ tôi đang sử dụng phần sau trong một trong các tập lệnh của tôi .so nằm trong cùng thư mục với tập lệnh python.

import os 
path = os.path.dirname(os.path.realpath(__file__)) 
dll = CDLL("%s/iface.so"%path) 

Trong trường hợp của bạn, những điều sau đây là đủ.

from ctypes import * 
lib = CDLL("/home/starlon/Projects/pyCFA635/lib/libevaluator.so") 
21

Ngay cả khi bạn cung cấp đường dẫn đầy đủ cho CDLL hoặc cdll.LoadLibrary(), bạn vẫn có thể cần đặt LD_LIBRARY_PATH trước khi gọi Python. Nếu thư viện được chia sẻ bạn tải một cách rõ ràng đề cập đến một thư viện được chia sẻ khác và không có "đường dẫn" được đặt trong .so cho thư viện đó, thì thư viện đó sẽ không được tìm thấy, ngay cả khi thư viện đã được tải. Đường dẫn trong thư viện chỉ định đường dẫn tìm kiếm sẽ được sử dụng để tìm kiếm các thư viện khác mà thư viện đó cần có

Ví dụ: tôi có một nhóm thư viện bên thứ ba độc lập không do tôi sản xuất. b.so tham khảo a.so. Thậm chí nếu tôi tải a.so trước:

ctypes.cdll.LoadLibrary('/abs/path/to/a.so') 
ctypes.cdll.LoadLibrary('/abs/path/to/b.so') 

tôi nhận được một lỗi trên tải thứ hai, bởi vì b.so đề cập đến chỉ đơn giản là 'a.so', mà không có một rPath, vv b.so doesn' Tôi biết đó là a.so. Vì vậy, tôi phải đặt LD_LIBRARY_PATH trước để bao gồm '/ abs/path/to'.

Để tránh phải đặt LD_LIBRARY_PATH, bạn sửa đổi mục nhập đường đi trong tệp .so. Trên Linux, có hai tiện ích tôi thấy rằng thực hiện điều này: chrpath, và patchelf. chrpath có sẵn từ kho lưu trữ Ubuntu. Nó không thể thay đổi rpath trên .so của mà không bao giờ có một. patchelf là linh hoạt hơn.

1

Biên dịch nhị phân của bạn với một rPath tương đối so với thư mục làm việc hiện tại như:

gcc -shared -o yourbinary.so yoursource.c otherbinary.so \ 
    -Wl,-rpath='.',-rpath='./another/relative/rpath' -fpic 

Sau đó, bạn có thể thay đổi thư mục làm việc trong python khi chạy với:

import os 
os.chdir('/path/to/your/binaries') 

Như thế này , trình tải cũng tìm thấy các thư viện động khác như otherbinary.so

+0

Điều này chỉ hoạt động khi thư mục làm việc của quá trình tải thư viện là thư mục của thư viện. Nếu không, đường dẫn thời gian chạy tương đối không thể tìm thấy phụ thuộc, thư mục có liên quan đến thư viện. – danny

Các vấn đề liên quan