Яйца в пути перед переменной среды PYTHONPATH - PullRequest
16 голосов
/ 13 мая 2011

Если у меня установлены пакеты из easy_install , к яйцам добавляется sys.path перед элементами в переменной PYTHONPATH.

Например, если у меня установлен пакет egg с именем foo , а также пакет с именем foo в текущем каталоге, а затем выполните следующее:

PYTHONPATH="." python
>>> import foo

Это будет использовать версию яйца foo вместо локального каталога. Проверка sys.path показывает, что яйца помещены перед элементами из PYTHONPATH. Это кажется сломанным. Есть ли способ отменить это поведение?

Ответы [ 3 ]

13 голосов
/ 13 мая 2011

К сожалению, это делается с помощью жестко закодированного шаблона глубоко внутри setuptools/command/easy_install.py. Вы можете создать пропатченные установочные инструменты с отредактированным шаблоном, но я не нашел чистого способа расширения easy_install извне.

Каждый раз, когда запускается easy_install, он восстанавливает файл easy_install.pth. Вот быстрый скрипт, который вы можете запустить после easy_install, чтобы удалить верхний и нижний колонтитулы из easy_install.pth. Вы можете создать скрипт оболочки для запуска сразу после easy_install:

#!/usr/bin/env python
import sys
path = sys.argv[1]
lines = open(path, 'rb').readlines()
if lines and 'import sys' in lines[0]:
    open(path, 'wb').write(''.join(lines[1:-1]) + '\n')

Пример:

% easy_install gdata
% PYTHONPATH=xyz python -c 'import sys; print sys.path[:2]'
['', '/Users/pat/virt/lib/python2.6/site-packages/gdata-2.0.14-py2.6.egg']

% ./fix_path ~/virt/lib/python2.6/site-packages/easy_install.pth
% PYTHONPATH=xyz python -c 'import sys; print sys.path[:2]'
['', '/Users/pat/xyz']

Для большей ясности, вот формат easy-install.pth:

import sys; sys.__plen = len(sys.path)
./gdata-2.0.14-py2.6.egg
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)

Две import sys линии - виновник, заставляющий яйца появляться в начале пути. Мой скрипт просто удаляет эти строки sys.path.

2 голосов
/ 17 августа 2017

Рассмотрите возможность использования параметра командной строки -S для подавления обработки *.pth:

python -c 'import sys; print("\n".join(sys.path))'
python -S -c 'import sys; print("\n".join(sys.path))'

https://docs.python.org/3/library/site.html#site.main

Вы также можете использовать -S с site.main() для задержки *.pth обработки до времени выполнения, скажем, для захвата исходного sys.path для добавления:

export PYTHONPATH=$(
  PYTHONPATH='' \
  python -c 'import sys; \
    sys.path.extend(sys.argv[1:]); old=list(sys.path); \
    import site; site.main(); \
    [ old.append(p) for p in sys.path if p not in old ]; \
    sys.path=old; \
    print ":".join(sys.path)' \
  $EXTRA_PATH $ANOTHER_PATH)

python -S ... # using explicit PYTHONPATH
  • Начать с явного пустого PYTHONPATH
  • Добавить в sys.path явно с помощью extension
  • Импорт сайта и звонок site.main()
  • Добавить новые пути к старому пути и затем установить его в sys.path
  • Печать с ":" для PYTHONPATH
  • python -S желательно для последующих запусков только с использованием $PYTHONPATH
  • python -S может или не может быть желательным при установке PYTHONPATH (в зависимости от того, требуется ли расширение sys.path перед расширением)
1 голос
/ 19 февраля 2013

Я сделал что-то вроде следующего, чтобы добавить к системному пути при запуске исполняемого файла python верхнего уровня:

import sys
sys.path = ["<your python path>"] + sys.path

Часто "<your python path>" для меня предполагает использование атрибута __file__ для относительного поиска пути, включающего модуль верхнего уровня для моего проекта. Это не рекомендуется для использования при производстве яиц, хотя я, кажется, не против последствий. Может быть другая альтернатива __file__.

...