Импорт, пути, каталоги и модули Python - PullRequest
6 голосов
/ 23 августа 2011

Позвольте мне начать с того, что я провел обширные исследования в течение прошлой недели и еще не нашел реальных ответов на эти вопросы - только некоторые нечеткие ответы, которые на самом деле не объясняют, что происходит.Если это просто потому, что я пропустил то, что искал, извините - пожалуйста, просто укажите мне правильное направление.

Моя структура каталогов:

TestProject/
    runtest*
    testpackage/
        __init__.py
        testmod.py
        testmod2.py
        testsubs/
            testsubmod.py

Пара замечаний:

  • Я использую python2.7 в Ubuntu
  • Я тестирую с помощью bpython
  • Я запускаю bpython из определенных каталогов, чтобы проверить поведение импорта
  • Я пытаюсь следовать рекомендациям.
  • Этот пакет не установлен, он находится в случайном каталоге dev
  • Этот каталог не находится в pythonpath
  • У меня есть один init .py в каталоге пакетов
  • В вложенных каталогах нет init .py файлов
  • The init .py файл пуст
  • testpackage / testmod.py содержит TestModClass
  • testpackage / testsubs / testsubmod.py содержит TestSubModClass

Things Iнаблюдал:

  • Когда я запускаю bpython из TestProject / import testpackage works
    • Это не импортирует testpackage.testmod
    • Я не могу получить доступ к testpackage.testmod вообще
  • Когда я запускаю bpython из TestProject / импорт testpackage.testmod завершается неудачей
  • Когда я запускаю bpython из TestProject / из testpackage, импорт testmod работает
  • Я могу добавить код в init .py, чтобы явно импортировать testmod.py, но не testubs / testmod.py
    • Я не думаю, что это правильный способ сделать это, что если пользователь не хочет импортировать этот модуль?
  • из testmod.py Я могу импортировать testmod2, но не testpackage.testmod2
    • Было бы неплохо сделать так, чтобы я мог называть свои собственные модули с перекрывающимися именами с помощью STLили скрученный (например, testpackage.logging), не вызывающий ошибок (это отстойно называть мои собственные модули хламом, как customerlogging, а не просто mypackage.logging)

Ивопросы:

  1. Отличается ли PythonВ частности, при импорте пакетов и модулей, которые существуют в pythonpath, чем при попытке импорта из текущего каталога?
  2. Почему импорт testpackage не дает мне доступ к testpackage.testmod?Когда я импортирую os, я могу получить доступ к os.path (и т. Д.).
  3. С пакетом, следует ли мне использовать один init .py в базовом каталоге иливкладывать их в последующие каталоги?
  4. Как мне импортировать модуль с указанием имени пакета?IE из testmod.py, я хотел бы импортировать testpackage.testmod2, а не просто testmod2.
  5. Как правильно импортировать подмодули из каталога sububs?
    1. Единственное решение, которое я вижу, это добавить этот каталог в pythonpath из init .py, но я не знаю, правильный ли это путь.

Заранее спасибо.

Ответы [ 2 ]

8 голосов
/ 23 августа 2011

Прежде всего, вы найдете всю необходимую информацию в разделе 6 Учебника по Python .


(1) По-разному ли python обрабатывает импорт пакетов и модулей, существующих в pythonpath, по сравнению с тем, когда вы пытаетесь импортировать из текущего каталога?

Нет, это не так. На самом деле, Python всегда ищет sys.path при импорте модулей. Модули в текущем каталоге находятся только потому, что sys.path содержит запись с пустой строкой, означающей текущий каталог.


(2) Почему import testpackage не дает мне доступа к testpackage.testmod? Когда я импортирую os, я могу получить доступ к os.path (и т. Д.).

Для эффективности import testpackage загружает только testpackage/__init__.py. Если вам нужно testpackage.testmod, вам нужно явно импортировать его:

import testpackage   # Just imports testpackage, not testpackage.testmod!
import testpackage.testmod   # Import *both* testpackage and testpackage.testmod!

Если вы всегда хотите экспортировать testmod, импортируйте его в __init__.py, это то, что делает os (os/__init__.py). Таким образом, testpackage.testmod всегда доступен неявно, если вы импортируете testpackage.

Поскольку Python является кроссплатформенным, фактически невозможно последовательно и автоматически загружать модули в каталог, поскольку некоторые файловые системы нечувствительны к регистру (Windows!). Python не знает, загружать ли os/path.py как os.path или os.Path и т. Д.


(3) Следует ли с пакетом использовать один __init__.py в базовом каталоге или вкладывать их в последующие каталоги?

Вам всегда нужно __init__.py для каждого подпакета. Были дискуссии об отмене этого требования, но было решено оставить его как есть.


(4) Как я могу импортировать модуль с указанием имени пакета? И.Е. из testmod.py я бы хотел импортировать testpackage.testmod2, а не просто testmod2.

Это должно работать. Просто убедитесь, что вы запускаете код из каталога верхнего уровня. Если текущий каталог testpackage, testmod не знает, что он в пакете.

Предпочтительным способом является использование относительного импорта внутри пакета, хотя:

from . import testmod2

Это предотвращает конфликт имен, если существует глобальный модуль с именем testmod2, и позволяет без проблем использовать имена известных модулей в вашем пакете.


(5) Как правильно импортировать подмодули из каталога sububs? Единственное решение, которое я вижу, - добавить этот каталог в pythonpath из __init__.py, но я не знаю, правильный ли это путь.

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

Обычно вы можете загружать модули из подпакетов, используя абсолютный или относительный импорт:

import testpackage.testsubs.testsubmod
from testpackage.testsubs import testsubmod
from .testsubs import testsubmod

Просто создайте __init__.py в testsubs/!

0 голосов
/ 23 августа 2011
  1. Нет. Текущий каталог только что добавлен в PYTHONPATH.
  2. Во-первых, вам нужен __init__.py. Во-вторых, os.path приходит, потому что os импортирует os.path.
  3. Вам нужен __init__.py в каждом каталоге , также в каталоге, содержащем каталог testpackage.
  4. В пакете __init__.py импортируйте модули, которые вы хотите предоставить.
  5. из субмодуля импорта sub1.sub2
    1. Нет, если самый верхний каталог находится в PYTHONPATH, а этот и его подкаталоги имеют свой __init__.py, это все, что вам нужно импортировать из любого из подкаталогов.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...