PYTHONPATH против sys.path

93

Другой разработчик и я не согласны с тем, следует ли использовать PYTHONPATH или sys.path, чтобы позволить Python найти пакет Python в каталоге пользователя (например, разработчика).

У нас есть проект Python с типичной структурой каталогов:

Project
    setup.py
    package
        __init__.py
        lib.py
        script.py

В script.py нам нужно сделать import package.lib. Когда пакет установлен в site-packages, можно найти script.py package.lib.

Однако при работе из пользовательского каталога необходимо сделать кое-что еще. Мое решение - включить в PYTHONPATH «~ / Project». Другой разработчик хочет поместить эту строку кода в начало script.py:

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

Чтобы Python мог найти локальную копию package.lib.

Я думаю, что это плохая идея, так как эта строка полезна только для разработчиков или людей, работающих с локальной копией, но я не могу объяснить, почему это плохая идея.

Должны ли мы использовать PYTOHNPATH, sys.path или все в порядке?

гефан
источник
4
Похоже, голоса и ответы разделены довольно поровну с очень небольшим уклоном в сторону использования PYTHON_PATH, хотя это может быть шум выборки или непреднамеренное смещение из вопроса.
AJP
Для разницы между PATHи sys.path(и косвенно PYTHONPATH) см. Также stackoverflow.com/questions/25344841/sys-path-vs-path
tripleee

Ответы:

42

Если единственная причина для изменения пути - это разработчики, работающие из своего рабочего дерева, тогда вам следует использовать инструмент установки, чтобы настроить вашу среду за вас. virtualenv очень популярен, и если вы используете инструменты установки, вы можете просто запустить, setup.py developчтобы частично установить рабочее дерево в текущей установке Python.

Нед Батчелдер
источник
11
Не могли бы вы пояснить это подробнее? Даже если вы встанете в среду conda / virtualenv, как это поместит каталог верхнего уровня на ваш путь Python?
compguy24
38

Я ненавижу PYTHONPATH. Мне кажется хрупким и неприятным устанавливать его для каждого пользователя (особенно для пользователей демонов) и отслеживать перемещение папок проекта. Я бы предпочел установить sys.pathскрипты вызова для автономных проектов.

Однако sys.path.appendэто не способ сделать это. Вы можете легко получить дубликаты, и он не сортирует .pthфайлы. Лучше (и более читаемым): site.addsitedir.

И script.py, как правило, это не более подходящее место для этого, поскольку оно находится внутри пакета, который вы хотите сделать доступным по пути. Модули библиотеки, конечно, не должны касаться sys.pathсамих себя. Вместо этого у вас обычно есть hashbanged-script вне пакета, который вы используете для создания экземпляра и запуска приложения, и в этот тривиальный сценарий-оболочку вы помещаете детали развертывания, такие как sys.path-frobbing.

бобинс
источник
17
Проблема в site.addsitedirтом , что он делает appendON sys.path, а это означает , что установленный пакет будет иметь приоритет над местным пакетом в развитии (и таскание за волосы могут наступить). sys.path.insert(0...необходимо преодолеть это.
Эли Бендерский
5
@EliBendersky: должно быть sys.path.insert(1. stackoverflow.com/q/10095037/125507
endolith
12

В общем, я считаю настройку переменной окружения (например, PYTHONPATH) плохой практикой. Хотя это может быть хорошо для разовой отладки, но использование этого в
качестве обычной практики может быть не очень хорошей идеей.

Использование переменной окружения приводит к ситуациям типа «у меня работает», когда кто-
то сообщает о проблемах в базе кода. Также можно применить ту же практику к тестовой среде, что приведет к таким ситуациям, как тесты работают нормально для конкретного разработчика, но, вероятно, не работают, когда кто-то запускает тесты.

сатиш
источник
6

Наряду со многими другими причинами, уже упомянутыми, вы также можете указать на то, что жесткое кодирование

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

является хрупким, потому что предполагает расположение script.py - он будет работать, только если script.py находится в Project / package. Он сломается, если пользователь решит переместить / скопировать / символическую ссылку script.py (почти) куда-нибудь еще.

Unutbu
источник
5

Я думаю, что в этом случае использование PYTHONPATH лучше, в основном потому, что он не вводит (сомнительный) ненужный код.

В конце концов, если вы думаете об этом, вашему пользователю это не нужно sys.path, потому что ваш пакет будет установлен в пакеты сайтов, потому что вы будете использовать систему упаковки.

Если пользователь выбирает запуск из «локальной копии», как вы это называете, то я заметил, что обычная практика состоит в том, чтобы указать, что пакет необходимо добавить в PYTHONPATH вручную, если он используется вне пакетов сайта. .

хитрый
источник
3

Ни взлом, PYTHONPATHни sys.pathхорошая идея по указанным выше причинам. И для связывания текущего проекта с папкой site-packages на самом деле есть лучший способ, чем python setup.py developописанный здесь :

pip install --editable path/to/project

Если у вас еще нет setup.py в корневой папке вашего проекта, этого достаточно, чтобы начать с:

from setuptools import setup
setup('project')
Питер
источник