Как Python отслеживает модули, установленные с яйцами?
Если у меня есть модуль, foo
, в Lib/site-packages
, я могу просто import foo
, и он будет работать. Однако, когда я устанавливаю вещи из яиц, я получаю что-то вроде blah-4.0.1-py2.7-win32.egg
в виде папки с содержимым модуля внутри, но мне все еще нужно сделать import foo
, а не что-то более сложное. Как Python отслеживает яйца? Это не просто сопоставление dirname, как если бы я удалял эту папку в установку Python, не проходя через dist-utils, он не нашел модуль.
Чтобы быть яснее: я только что установил zope. Имя папки - "zope.interface-3.3.0-py2.7-win32.egg". Это работает:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import zope.interface
>>>
Я создаю папку "blah-4.0.1-py2.7-win32.egg" с пустым модулем "haha" в ней (и __init__.py
). Это не работает:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import blah.haha
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named blah.haha
>>>
Это делает, хотя:
Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from pkg_resources import require
>>> require("blah>=1.0")
[blah 4.0.1 (c:\python27\lib\site-packages\blah-4.0.1-py2.7-win32.egg)]
>>> import haha
>>>
Итак, как мне заставить работать без require
?
Ответы
Ответ 1
Если вы используете easy_install
script, предоставленный setuptools
(или его Distribute
) для установки пакетов как яйца, вы увидите, что по умолчанию он создает файл с именем easy-install.pth
в каталоге site-packages
вашей установки Python. Файлы конфигурации пути являются стандартной функцией Python:
Файл конфигурации пути - это файл чье имя имеет форму package.pth и существует в одном из четырех упомянутые выше каталоги; его содержимое - дополнительные предметы (по одному в line) для добавления в sys.path.
easy_install
сильно использует эту функцию Python. Когда вы используете easy_install
для добавления или обновления дистрибутива, он изменяет easy-install.pth
, чтобы добавить каталог яиц или zip файл. Таким образом, easy_install
поддерживает управление порядком поиска модуля и гарантирует, что яйца, которые он устанавливает, появляются в начале порядка поиска. Ниже приведен пример содержимого easy-install.pth
:
import sys; sys.__plen = len(sys.path)
./appscript-0.21.1-py2.6-macosx-10.5-ppc.egg
./yolk-0.4.1-py2.6.egg
./Elixir-0.7.1-py2.6.egg
./Fabric-0.9.0-py2.6.egg
import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginse
rt',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)
Как вы можете видеть здесь, и если вы изучите код в setuptools
, вы обнаружите, что он подходит к некоторому обману для самонастройки, а затем охватывает его треки, которые могут сделать проблемы отладки с помощью site.py
и запуск интерпретатора немного интересным, (Это одна из причин, по которой некоторые разработчики не любят ее использовать.)
Если вы используете параметр -m
easy_install
для установки дистрибутива в виде нескольких версий, запись easy-install.pth
для него не добавляется или удаляется, если она уже существует. Вот почему easy_install
документация сообщает вам использовать -m
перед удалением установленного яйца.
Ответ 2
Когда вы запускаете easy_install, он копирует яйцо в пакеты-сайты и помещает путь к этому яйцу в вашу переменную sys.path. (Обратите внимание, что sys.path не является вашей переменной среды PATH, она построена из PYTHONPATH и других переменных среды. Таким образом, файл .egg, который вы устанавливаете с помощью easy_install, помещается в некоторую переменную среды, и python знает, чтобы добавить его в sys.path, когда запущен интерпретатор python).
Чтобы заставить blah.haha работать в вашем примере, запустите easy_install blah-4.0.1-py2.7-win32.egg
, а затем вы можете import haha
изнутри python или просто поместите модуль haha непосредственно в пакеты сайта.