Макет проекта Python и каталогов пакетов

Я создал проект в python, и мне интересно, как пакеты работают на python.

Вот мой макет каталога:

top-level dir
  \ tests
    __init__.py 
  \ examples
    __init__.py
    example.py
module.py

Как я могу включить module.py в мой модуль example.py. Я знаю, что могу установить PYTHONPATH в каталог верхнего уровня, но это не похоже на хорошее решение. Вот как pydev обошел эту проблему, но я бы хотел, чтобы решение не требовало обновления переменных среды.

Я мог бы поставить что-то наверху example.py для обновления sys.path следующим образом:

from os import path
import sys

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

Я не думаю, что это подходящее решение.

Я чувствую, что у меня отсутствует основная часть пакетов python. Я тестирую это на python 2.6. Если потребуется какое-либо уточнение, сообщите мне.

Ответ 1

Пакеты Python очень просты: пакет представляет собой любой каталог под любой записью в sys.path с файлом __init__.py. Тем не менее, модуль считается включенным только в пакет, если он импортируется через относительный импорт, такой как import package.module или from package import module. Обратите внимание, что это означает, что в общем случае кто-то должен установить sys.path, чтобы содержать каталоги над любым пакетом, который вы хотите импортировать, через PYTHONPATH или иначе.

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

В вашем случае я бы рекомендовал либо иметь небольшой Python script, который запускает ваши примеры после настройки правильного пути. Скажем, вы поместили его в каталог верхнего уровня:

#!/usr/bin/env python
import sys
import os.path

sys.path.append(os.path.dirname(__file__))
example = __import__("examples", globals(), locals(), sys.argv[1])

Тогда ваш пример может сделать "import module".

В качестве альтернативы, если module.py также должен быть в пакете, добавьте PARENT вашего "каталога верхнего уровня" в sys.path, а затем используйте синтаксис from .. import module в ваших примерных модулях. Кроме того, измените первый параметр на __import__ в обертке на "tldname.examples", где tldname - это имя вашего каталога верхнего уровня.

Если вы не хотите полагаться на модуль "примерный бегун", для каждого примера нужен шаблон sys.path, или вам нужен параметр PYTHONPATH. К сожалению.