Ustaw LD_LIBRARY_PATH przed zaimportowaniem w Pythonie


Python używa zmiennej środowiskowej
PYTHONPATH
, aby określić, które foldery mają szukać modułów.
Możesz się nim bawić, modyfikując
sys.path
, który działa dobrze dla czystych modułów Pythona.
Ale kiedy moduł używa współdzielonych plików obiektów lub bibliotek statycznych, szuka ich w
LD_LIBRARY_PATH
(na Linuksie), ale nie można tego tak łatwo zmienić i o ile wiem, zależy to od platformy.
Szybkim rozwiązaniem tego problemu jest oczywiście ustawienie zmiennej środowiskowej lub wywołanie skryptu, takiego jak
LD_LIBRARY_PATH =. ./script.py
, ale potem musisz zainstalować go ponownie dla każdej nowej powłoki, którą otwierasz.
Ponadto pliki
.so
w moim przypadku zawsze będą znajdować się w tym samym katalogu co plik
.py
, ale można je bardzo dobrze przenieść do innej ścieżki bezwzględnej, więc Wanted ustawiałby je automatycznie za każdym razem, gdy wywołuję skrypt.

Jak mogę edytować ścieżkę, w której interpreter języka Python szuka bibliotek platformy - niezależnie od środowiska uruchomieniowego?


EDIT:
>
Próbowałem już
os.environ ['LD_LIBRARY_PATH'] = os.getcwd ()
, ale bezskutecznie.
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Użyłbym:
import osos.environ['LD_LIBRARY_PATH'] = os.getcwd() # or whatever path you want

W tym przypadku zmienna środowiskowa
LD_LIBRARY_PATH
jest ustawiana tylko na czas trwania bieżącego procesu.

EDIT:

wygląda na to, że należy go zainstalować przed uruchomieniem Pythona:

zmiana LD_LIBRARY_PATH w czasie wykonywania dla ctypów
https://coderoad.ru/856116/
Dlatego sugerowałbym użycie skryptu opakowującego
.sh
(lub
.py
, jeśli nalegasz). Ponadto, jak zauważył @chepner, możesz rozważyć zainstalowanie plików
.so
w standardowej lokalizacji (w ramach virtualenv).
Zobacz także sekcję

ustawienie LD_LIBRARY_PATH z poziomu Pythona
https://coderoad.ru/6543847/
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Moim rozwiązaniem tego problemu jest umieszczenie tego w pierwszej linii skryptu Pythona (zamiast zwykłego shebang):
exec env LD_LIBRARY_PATH=/some/path/to/lib/path/to/specific/python -x "$0" "$@"

A tak to działa:
  • bez shebang, bieżąca powłoka traktuje plik jako skrypt powłoki,
  • "exec" zapewnia, że ​​ta pierwsza linia jest jednocześnie ostatnią komendą powłoki z tego pliku,
  • „env” jest tutaj używane do ustawiania dowolnych zmiennych środowiskowych, takich jak LD_LIBRARY_PATH, [*]dokładną ścieżkę do interpretera Pythona można określić lub "env" może go znaleźć w PATH,
  • [/*]
  • „-x” to opcja języka Python, która powoduje, że interpreter języka Python ignoruje pierwszą linię,
  • „$ 0” to nazwa skryptu, „$ @” jest zastępowane parametrami pozycyjnymi.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Python, gdy pobiera wartości zmiennych środowiskowych, takich jak
os.environ ['LD_LIBRARY_PATH']
lub
os.environ ['PATH']
, kopiuje wartości Do słownika z procesu środowiska nadrzędnego, zwykle bash (środowisko bash procesu get jest przenoszone do procesu potomnego, na którym działa instancja Pythona).
możesz zobaczyć tę sekcję zmiennej środowiskowej z wyjściem polecenia
env
z bash.
możesz również zobaczyć/odczytać te dane env z
/ proc/& < pid & >/environment
, wprowadzając nieskończoną pętlę (
while 1: pass
) po zmianie dowolnego Zmienna środowiskowa.
Jeśli zobaczysz/przeczytasz wartość/dane tej zmiennej z
/ proc/& < pid & >/environment
po zmianie jej w skrypcie Pythona, zobaczysz, że rzeczywiste dane zmiennej nie ulegają zmianie, chociaż skrypt Pythona pokazuje zaktualizowany klucz słownika wartości zmienionych.
To, co się właściwie dzieje, gdy zmienisz zmienną env w skrypcie Pythona, tak jak w skrypcie
os.environ ['LD_LIBRARY_PATH'] = '/ & < new_location & >'
, polega na tym, że po prostu aktualizuje wartość w lokalnym słowniku, który nie odpowiada sekcji zmiennej env procesu. Dlatego nie będzie propagować się całkowicie wstecz, aby odzwierciedlić się w środowisku bieżącego procesu, ponieważ

TYLKO lokalny słownik

został zmodyfikowany/zaktualizowany/wypełniony.
Dlatego też, jeśli chcemy, aby nowa zmienna środowiskowa została odzwierciedlona, ​​musimy nadpisać obraz pamięci procesu danymi nowej zmiennej środowiskowej za pomocą
execv
.

Przykład

:
new_lib = '/<new_location>'
if not new_lib in os.environ['LD_LIBRARY_PATH']:
os.environ['LD_LIBRARY_PATH'] += ':'+new_lib
try:
os.execv(sys.argv[0], sys.argv)
except Exception as e:
sys.exit('EXCEPTION: Failed to Execute under modified environment, '+e)import xyz
#do something else


Ograniczenie
: idealnie byłoby, gdyby python nie pozwalał na taką modyfikację zmiennych
os.environ
.
Ponieważ jednak słownik nie ma stałego typu danych, umożliwia zmianę zmiennej danych. Nie ma absolutnie sensu zmieniać wartości, ponieważ nie daje to nic przydatnego do odzwierciedlenia w rzeczywistym środowisku działającego procesu, chyba że zostanie użyte
execv
.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Rozwiązanie działa świetnie, jeśli środowisko env jest ponownie zainicjowane
import osos.environ['LD_LIBRARY_PATH'] = os.getcwd() # or whatever path you want

Kod należy zaakceptować lokalnie ....
os.execv(sys.argv[0], sys.argv)

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się