Установите путь к библиотеке LD перед импортом в python

Python использует PYTHONPATH environment-переменная, чтобы определить, в каких папках она должна искать модули. Вы можете поиграть с ним, изменив sys.path, который отлично работает для чистых Python-модулей. Но когда модуль использует общие объектные файлы или статические библиотеки, он ищет их в LD_LIBRARY_PATH (в linux), но это не может быть изменено так легко и зависит от платформы, насколько я знаю.

быстрое исправление для этой проблемы, конечно, установить переменную окружения или вызовите скрипт как LD_LIBRARY_PATH=. ./script.py, но тогда вам придется установить его снова для каждой новой оболочки, которую вы открываете. Кроме того,.so файлы, в моем случае всегда будет находиться в том же каталоге, что .py файл, но вполне может быть перемещен на другой абсолютный путь, поэтому я хотел бы установить их автоматически каждый раз, когда я вызываю скрипт.

как я могу редактировать путь, в котором интерпретатор Python ищет платформу библиотек-независимо от время выполнения?

EDIT:

Я уже пробовал os.environ['LD_LIBRARY_PATH'] = os.getcwd(), но безрезультатно.

3 ответов


Я хотел бы использовать:

import os

os.environ['LD_LIBRARY_PATH'] = os.getcwd()  # or whatever path you want

установка LD_LIBRARY_PATH переменная окружения только для продолжительности / времени жизни выполнения текущего процесса.

EDIT: похоже, это нужно установить перед запуском Python:изменение LD_LIBRARY_PATH во время выполнения для ctypes

поэтому я бы предложил пойти с оберткой .sh (или .py Если вы настаиваете) сценарий. Также, как @chepner указал, вы, возможно, захотите рассмотреть вопрос об установке ваш .so файлы в стандартном расположении (в пределах virtualenv).

см. также настройка LD_LIBRARY_PATH изнутри Python


мое решение этой проблемы заключается в том, чтобы поместить это как первую строку скрипта Python (вместо обычного shebang):

exec env LD_LIBRARY_PATH=/some/path/to/lib /path/to/specific/python -x "" "$@"

и вот как это работает:

  • без shebang текущая оболочка обрабатывает файл как сценарий оболочки,
  • "exec" гарантирует, что эта первая строка также является последней командой из этого файла, выполняемой оболочкой,
  • " env " используется здесь для установки любых переменных среды, например LD_LIBRARY_PATH,
  • an точный путь к интерпретатору Python может быть указан или " env " может найти его в PATH,
  • " - x " - это опция Python, которая заставляет первую строку игнорироваться интерпретатором Python,
  • "$0" - это имя скрипта, "$@" заменяется позиционными параметрами.

Python, когда получает значения переменных среды, как в os.environ[‘LD_LIBRARY_PATH’] или os.environ[‘PATH’], он копирует значения в словарь из среды родительского процесса, как правило, bash (среда bash process get переносится в дочерний процесс, запущенный экземпляр python).

вы можете увидеть этот раздел переменной среды с env вывод команды из bash.

вы также можете увидеть / прочитать эти данные env из /proc/<pid>/environ, введя бесконечное петля(while 1: pass) после изменения любой переменной среды.

если вы видите / читаете это значение переменной / данные из /proc/<pid>/environ после изменения его внутри скрипта python вы увидите, что данные реальной переменной не изменяются, хотя скрипт python показывает измененное значение ключа словаря, обновленное.

что на самом деле происходит при изменении переменной env внутри скрипта python, как в os.environ['LD_LIBRARY_PATH']='/<new_location>', это просто обновляет значение в локальном словаре, которое не сопоставляется с переменным разделом env процесса. Следовательно, он не будет распространяться полностью назад, чтобы отразить в среде текущего процесса, потому что только локальный словарь был изменен/обновлен / заполнен.

следовательно, если мы хотим, чтобы новая переменная среды была отражена, мы должны перезаписать образ памяти процесса новыми данными переменной среды, используя execv.

пример:

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

ограничение: в идеале python не должен допускать такой модификации os.environ переменные. Но поскольку нет постоянного типа данных словаря, он позволяет изменять переменную данных. Нет абсолютно никакого смысла изменять значения, поскольку он не делает ничего полезного для отражения в реальной среде запущенного процесса, если это.