Проблемы с несколькими версиями Python 2.x относительно PYTHONPATH

В системе установлен Python 2.6.

Теперь я хочу использовать модули, представленные в Python 2.7. Поскольку у меня нет привилегий root, я собрал и установил 2.7 в своем домашнем каталоге ($ HOME / local /)

Я добавил в свой $ HOME / .bashrc следующее:

export PATH=$HOME/local/bin:$PATH
export PYTHONPATH=$HOME/local/lib/python2.7:$PYTHONPATH

Теперь я столкнулся с двумя проблемами, и я хочу попросить их обходные пути.

1. Вызов Python 2.7

Недавно установленный Python 2.7 не находит модули 2.6 в пути к системной библиотеке (/usr/lib/python2.6/site-packages/).

Стоит ли добавлять его в PYTHONPATH вручную? Есть ли более приятное решение?

2. Вызов Python 2.6

Python 2.6 при запуске жалуется:

'import site' failed; use -v for traceback

Я предполагаю, что он пытается загрузить модули 2.7 (в $ HOME / local / lib / python2.7). Можно ли загружать только модули 2.6 при вызове Python 2.6?

Спасибо.


person niboshi    schedule 04.03.2012    source источник


Ответы (3)


1) Вызов Python 2.7

Вкратце: не делайте этого. Есть причины, по которым путь называется '/ usr / lib / python * 2.6 * / site-packages /'.

Одна из причин заключается в том, что в этом каталоге обычно хранятся «скомпилированные» файлы Python (.pyc). Файлы python 2.6 и python 2.7 .pyc несовместимы:

$ python2.7 /usr/lib/python2.6/sitecustomize.pyc
RuntimeError: Bad magic number in .pyc file

python пропустит файлы pyc, которые он не может понять, но вы потеряете, по крайней мере, преимущества предварительно скомпилированных файлов.

Другая причина в том, что все может перепутаться:

$ strace -f python2.7 /usr/lib/python2.6/sitecustomize.py
...
stat("/etc/python2.6", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/etc/python2.6", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/etc/python2.6/apport_python_hook", 0x7fffa15601f0) = -1 ENOENT (No such file or directory)
open("/etc/python2.6/apport_python_hook.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/python2.6/apport_python_hookmodule.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/python2.6/apport_python_hook.py", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/etc/python2.6/apport_python_hook.pyc", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib/python2.7/apport_python_hook", 0x7fffa15601f0) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.7/apport_python_hook.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.7/apport_python_hookmodule.so", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.7/apport_python_hook.py", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/lib/python2.7/apport_python_hook.pyc", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib/python2.7/plat-linux2/apport_python_hook", 0x7fffa15601f0) = -1 ENOENT (No such file or directory)
...

В вашем случае я бы установил модули, необходимые также для python 2.7, в каталог python2.7.

2) Вызов Python 2.6

Возможно, вы захотите взглянуть на ту часть справочной страницы, где описывается PYTHONHOME:

PYTHONHOME: изменить расположение стандартных библиотек Python. По умолчанию библиотеки ищутся в $ {prefix} / lib / python [версия] и $ {exec_prefix} / lib / python [версия], где $ {prefix} и $ {exec_prefix} являются каталогами, зависящими от установки, оба значения по умолчанию в / usr / local

Вы можете сохранить определенные файлы / модули Python 2.7 в соответствующем каталоге в вашей локальной установке. Эти файлы / модули будут получены только при запуске определенной версии python. В этом случае вы не должны устанавливать PYTHONPATH (или PYTHONHOME).

Примечание: именно так Debian (и, возможно, другие дистрибутивы) управляет разными одновременно установленными версиями python.

[Edit: Добавлен раздел 1 после получения комментария от нибоши.]

person Andreas Florath    schedule 04.03.2012
comment
Я думаю, что проблема 2 должна быть решена с этим, а проблема 1 - нет. В любом случае спасибо за то, что рассказали мне о PYTHONHOME. - person niboshi; 05.03.2012

При запуске Python берет PYTHONPATH переменную среды и помещает ее в sys.path переменную. Когда вы пытаетесь импортировать модуль, он смотрит на пути в sys.path

Из-за:

export PYTHONPATH=$HOME/local/lib/python2.7:$PYTHONPATH

ваши пути Python 2.7 находятся в начале sys.path, перед путями Python 2.6 (вы можете print sys.path проверить). Это означает, что модули из $HOME/local/lib/python2.7 будут иметь приоритет.

Чтобы настроить пути для некоторых из ваших сценариев, либо установите PYTHONPATH для каждого сценария, либо измените sys.path (sys.path.insert(0, '/home/user/local/lib/python2.7') прямо в сценарии до того, как будет выполнен импорт.

Или скопируйте конкретный модуль в свой проект под другим именем. Например, я скопировал модуль collections из Python 2.7 в свой проект с помощью collections27.py, а в тех местах, где мне нужно OrderedDict, я делаю from collection27 import OrderedDict

Можно ли загружать только модули 2.6 при вызове Python 2.6?

Я полагаю, да. Просто убедитесь, что в пути есть только модули Python 2.6 - не используйте:

export PYTHONPATH=$HOME/local/lib/python2.7:$PYTHONPATH
person warvariuc    schedule 04.03.2012
comment
1. Вы можете скопировать, например, collections.py (и другие необходимые вам модули в папку вашего проекта. В директории вашего проекта выполняется поиск модулей в первую очередь, поэтому, когда вы сделаете это import collections, будет импортирован модуль из папки вашего проекта. Настройте PYTHONPATH. Если вы хотите, чтобы библиотеки из Python 2.6 имели приоритет - сначала укажите их пути. Примечание: проверьте, какие пути используются для печати sys.path в вашем скрипте. - person warvariuc; 05.03.2012

Могу я предложить pythonbrew в качестве более простой альтернативы.

После установки pythonbrew:

$ pythonbrew install 2.7.2
$ pythonbrew switch 2.7.2
person Burhan Khalid    schedule 04.03.2012
comment
Выглядит неплохо. Но поскольку сеть недоступна в моей системе, я не могу ее использовать. - person niboshi; 05.03.2012