Импорт локальной тестовой версии пакета пространства имен Python

Мне интересно, как я могу импортировать локальную тестовую версию пакета пространства имен Python 2.7. В этом примере пакет Ska.engarchive это пакет пространства имен под Ska корень. (Эта структура навязана мне наследием).

Этот пример показывает, что даже после настройки sys.path чтобы начать с локального каталога, импортируется установленная версия пакета, а не локальная версия.

Python 2.7.9 |Continuum Analytics, Inc.| (default, Apr 14 2015, 12:54:25)
... 
In [1]: import sys
In [2]: sys.path.insert(0, '.')
In [3]: import Ska.engarchive.fetch_eng as fetch
In [4]: fetch.__file__
Out[4]: '/proj/sot/ska/arch/x86_64-linux_CentOS-5/lib/python2.7/site-packages/Ska.engarchive-0.36.2-py2.7.egg/Ska/engarchive/fetch_eng.pyc'

Я думаю, что проблема связана с тем, как пакеты пространств имен реализованы в Python 2, и каким-то образом пути к пространствам имен всегда находятся в начале списка, несмотря ни на что. Но, может быть, есть какой-то обходной путь? Я провел некоторое время, копаясь вокруг site пакет документов, но, может быть, я просто не видел нужную вещь.

Приведенный выше пример использует дистрибутив Anaconda Python. Интересно, что если я использую действительно старую сборку Python из ActiveState, в примере получится желаемый результат импорта локального пакета:

Python 2.7.1 (r271:86832, Feb  7 2011, 11:30:54) 

In [1]: import sys
In [2]: sys.path.insert(0, '.')
In [3]: import Ska.engarchive.fetch_eng as fetch
In [4]: fetch.__file__
Out[4]: './Ska/engarchive/fetch_eng.pyc'

Любая помощь будет принята с благодарностью!

1 ответ

Решение

Мне удалось воспроизвести это поведение, используя метод setuptools для пакетов пространства имен (но не стандартный метод pkgutil). Setuptools импортирует установленный пакет, а pkgutil импортирует локальный пакет. Setuptools появляется для загрузки __path__ в обратном направлении от того, что вы ожидаете (установлено первое, локальное второе). Например, (см. Пример внизу для определения nstest)

>>> import nstest
>>> nstest.__path__
['/home/caleb/.local/lib/python2.7/site-packages/nstest.foo-0.0.0-py2.7.egg/nstest', 'nstest']

Чтобы обойти это, добавьте свой локальный пакет перед __path__ в самый правый пакет пространства имен. Например,

>>> import nstest
>>> nstest.__path__.insert(0, 'nstest')
>>> from nstest import foo
>>> foo.__file__
'nstest/foo/__init__.py'

Так как вы говорите в своем вопросе, что Ska.engarchive пакет пространства имен, в вашем интерпретаторе вы хотите сделать следующее:

>>> import Ska.engarchive
>>> Ska.engarchive.__path__.insert(0, 'Ska/engarchive')
>>> import Ska.engarchive.fetch_eng as fetch
>>> fetch.__file__
'Ska/engarchive/fetch_eng.pyc' # This should be outputted

Проверка пространства имен с использованием pkg_resources в setuptools

Структура каталогов:

nstest.foo/
├─ setup.py
└─ nstest/
   ├─ __init__.py
   └─ foo/
      └─ __init__.py

nstest.foo/setup.py:

from setuptools import setup, find_packages
setup(name='nstest.foo', packages=find_packages())

nstest.foo/nstest/__init__.py:

__import__('pkg_resources').declare_namespace(__name__)

nstest.foo/nstest/foo/__init__.py:

# empty

Установка:

$ python2 setup.py build
$ python2 setup.py install --user

Тестовое задание:

$ python2
>>> from nstest import foo
>>> foo.__file__
'/home/caleb/.local/lib/python2.7/site-packages/nstest.foo-0.0.0-py2.7.egg/nstest/foo/__init__.pyc'
Другие вопросы по тегам