Заказ PYTHONPATH на Ubuntu 14.04
У меня есть два компьютера, на которых запущен сервер Ubuntu 14.04 (позвоните им A и B). B первоначально был 10,04, но он получил два обновления до 12,04 и 14,04. Я не понимаю, почему путь python отличается на двух компьютерах.
Как вы можете видеть на двух путях ниже, путь установки пакета /usr/local/lib/python2.7/dist-packages
доходит до до пути apt python пакетов /usr/lib/python2.7/dist-packages
на Ubuntu A, но он приходит после на Ubuntu B.
Это приводит к нескольким проблемам, если пакет python установлен как через apt, так и в pip. Как вы можете видеть ниже, если установлены пакет python-six
apt и six
pip, они могут быть двумя разными версиями библиотеки.
Установка системы пакетов не всегда является моим выбором, но может быть некоторыми зависимостями других установленных пакетов.
Эта проблема, вероятно, может быть решена с помощью virtualenv, но по причинам, которые я не буду подробно описывать, я не могу использовать virtualenv здесь и должен устанавливать пакеты пакетов в общесистемной области.
Ubuntu A
>>> import sys, six
>>> sys.path
['',
'/usr/local/bin',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PILcompat',
'/usr/local/lib/python2.7/dist-packages/IPython/extensions']
>>> six
<module 'six' from '/usr/local/lib/python2.7/dist-packages/six.pyc'>
Ubuntu B
>>> import sys, six
>>> sys.path
['',
'/usr/local/bin',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/PILcompat',
'/usr/local/lib/python2.7/dist-packages/IPython/extensions']
>>> six
>>> <module 'six' from '/usr/lib/python2.7/dist-packages/six.pyc'>
Для обеих машин $PATH
одинаков, а $PYTHONPATH
пуст.
-
Почему эти PYTHONPATHS отличаются?
-
Как я могу исправить порядок pythonpath в "Ubuntu B", чтобы он загружал пип
пакеты перед системными, в общесистемном режиме? Есть ли подходящий пакет, который я должен переустановить или переконфигурировать, чтобы
PYTHONPATH определил приоритет пакетов пакетов?
Ответы
Ответ 1
Как мы не можем исследовать вашу систему, я пытаюсь проанализировать ваш первый вопрос, проиллюстрировав, как инициализируется sys.path
. Доступными ссылками являются where-does-sys-path-starts и pyco-reverse -engineering (python2.6).
sys.path
исходит из следующих переменных (по порядку):
-
$PYTHONPATH
(наивысший приоритет)
-
sys.prefix
-ed stdlib
-
sys.exec_prefix
-ed stdlib
-
site-packages
-
*.pth
в пакетах сайтов (самый низкий приоритет)
Теперь опишите каждую из этих переменных:
-
$PYTHONPATH
, это просто переменная системной среды.
- & 3.
sys.prefix
и sys.exec_prefix
определяются до выполнения любого python script. Он фактически закодирован в источнике Module/getpath.c.
Логика такова:
IF $PYTHONHOME IS set:
RETURN sys.prefix AND sys.exec_prefix as $PYTHONHOME
ELSE:
current_dir = directory of python executable;
DO:
current_dir = parent(current_dir)
IF FILE 'lib/pythonX.Y/os.py' EXSITS:
sys.prefix = current_dir
IF FILE 'lib/pythonX.Y/lib-dynload' EXSITS:
sys.exec_prefix = current_dir
IF current_dir IS '/':
BREAK
WHILE(TRUE)
IF sys.prefix IS NOT SET:
sys.prefix = BUILD_PREFIX
IF sys.exec_prefix IS NOT SET:
sys.exec_prefix = BUILD_PREFIX
-
& 5. site-packages
и *.pth
добавляются путем импорта site.py
. В этом модуле вы найдете документы:
Это добавит пути к конкретному сайту для пути поиска модуля. На
Unix (включая Mac OSX), он начинается с sys.prefix и
sys.exec_prefix (если отличается) и добавляет
lib/python/site-packages, а также lib/site-python.
......
Для Debian и производных этот sys.path дополняется каталогами
для пакетов, распределенных в дистрибутиве. Локальные аддоны идут
в/usr/local/lib/python/dist-пакеты, дополнения Debian
установить в /usr/ {lib, share}/python/dist-packages.
/usr/lib/python/site -packages не используется.
Файл конфигурации пути - это файл, имя которого имеет форму
.pth; его содержимое - дополнительные каталоги (по одной в строке)
для добавления в sys.path.
......
И фрагмент кода для важной функции getsitepackages
:
sitepackages.append(os.path.join(prefix, "local/lib",
"python" + sys.version[:3],
"dist-packages"))
sitepackages.append(os.path.join(prefix, "lib",
"python" + sys.version[:3],
"dist-packages"))
Теперь я пытаюсь понять, где может возникнуть эта странная проблема:
-
$PYTHONPATH
, невозможно, потому что он пуст как A, так и B
-
sys.prefix
и sys.exec_prefix
, возможно, проверьте их, а также $PYTHONHOME
-
site.py
, возможно, проверьте файл.
Вывод sys.path
выхода B довольно нечетный, dist-package
(site-package
) идет до sys.exec_prefix
(lib-dynload
). Попробуйте исследовать каждый шаг sys.path
инициализации машины B, вы можете что-то узнать.
Очень жаль, что я не могу воспроизвести вашу проблему. Кстати, о вашем заголовке вопроса, я думаю, sys.path
лучше, чем PYTHONPATH
, что на первый взгляд делает меня неправильной интерпретацией как $PYTHONPATH
.
Ответ 2
Если вы заглянете в Python site.py
, что вы можете, открыв /usr/lib/python2.7/site.py
в текстовом редакторе.
sys.path дополняется каталогами для пакетов, распределенных в дистрибутиве. Локальные аддоны входят в /usr/local/lib/python/dist-packages
, глобальные аддоны устанавливаются в /usr/{lib,share}/python/dist-packages
.
Вы можете изменить порядок, переопределив это:
def getsitepackages():
"""Returns a list containing all global site-packages directories
(and possibly site-python).
For each directory present in the global ``PREFIXES``, this function
will find its `site-packages` subdirectory depending on the system
environment, and will return a list of full paths.
"""
sitepackages = []
seen = set()
for prefix in PREFIXES:
if not prefix or prefix in seen:
continue
seen.add(prefix)
if sys.platform in ('os2emx', 'riscos'):
sitepackages.append(os.path.join(prefix, "Lib", "site-packages"))
elif os.sep == '/':
sitepackages.append(os.path.join(prefix, "local/lib",
"python" + sys.version[:3],
"dist-packages"))
sitepackages.append(os.path.join(prefix, "lib",
"python" + sys.version[:3],
"dist-packages"))
else:
sitepackages.append(prefix)
sitepackages.append(os.path.join(prefix, "lib", "site-packages"))
if sys.platform == "darwin":
# for framework builds *only* we add the standard Apple
# locations.
from sysconfig import get_config_var
framework = get_config_var("PYTHONFRAMEWORK")
if framework:
sitepackages.append(
os.path.join("/Library", framework,
sys.version[:3], "site-packages"))
return sitepackages
Ответ 3
Здесь можно упомянуть то, что иногда файлы *.pth могут полностью испортить приоритеты, из которых вызывается sys.path.
Например, на моем 14.04 ubuntu/usr/local/lib/python2.7/dist-packages/easy-install.pth выглядит так:
import sys; sys.__plen = len(sys.path)
/usr/lib/python2.7/dist-packages
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)
Обратите внимание, что /usr/lib/python 2.7/dist-packages добавлено - даже до PYTHONPATH - это означает, что вы не можете реально повлиять на sys.path.
Чтобы ваши библиотеки /usr/local/lib/python 2.7/dist-packages имели приоритет, одним из вариантов является редактирование /usr/local/lib/python 2.7/dist-packages/easy-install.pth следующим образом:
import sys; sys.__plen = len(sys.path)
/usr/local/lib/python2.7/dist-packages
/usr/lib/python2.7/dist-packages
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)
Ответ 4
Самый простой способ - использовать sys.path, чтобы убедиться, что у вас будет правильный порядок добавленных путей. sys.path
выдает список путей, доступных в переменной среды PYHTONPATH
с правильным порядком. Если вы хотите, чтобы какой-либо путь имел более высокий приоритет над другими, просто добавьте его в начало списка.
И вы также найдете это в официальных документах:
Программа может изменять этот список в своих целях.
ПРЕДУПРЕЖДЕНИЕ. Несмотря на то, что это обеспечивает лучший контроль над приоритетом, просто убедитесь, что какая-либо библиотека, которую вы добавляете, не возится с системными библиотеками. В противном случае ваша библиотека будет искать сначала, так как она находится в начале списка, и они могут заменить системные библиотеки. Как пример, если вы написали библиотеку по имени os
, добавив ее в sys.path
, эта библиотека будет импортирована вместо встроенного Python. Поэтому примите все меры предосторожности, а также с большим количеством соли, прежде чем прыгать на это.
Ответ 5
PYTHONPATH - это переменная окружения, которую вы можете установить, когда хотите, добавить дополнительные каталоги. Вы не должны устанавливать пакеты Python вручную, используйте pip
. На старшем Ubuntu, возможно, вы установили вручную модули перед обновлением.