Каков правильный способ импорта модулей в библиотеку python?

Когда вы пишете библиотеку python и хотите импортировать в нее один модуль из другого, что это правильный способ сделать это, чтобы импорт работал как при импорте библиотеки извне, так и при выполнении некоторых модульных тестов из каталога библиотеки?

Если вы это сделаете

import some_module
from some_module import something

он работает при запуске из каталога библиотеки, но при импорте извне создает ImportError: No module named 'some_module'.

Ты можешь сделать

from . import some_module
import my_library.some_other_module
from .some_module import something

но он не будет работать, если вы импортируете библиотеку из unittest, помещенной в тот же каталог.

Наконец, вы можете играть с sys.path и/или переносить тесты модулей в другой каталог.

Какое лучшее решение?

Изменить: просто для того, чтобы это было ясно, я хотел бы запустить unittests, используя python -m unittest в верхнем каталоге библиотеки. Пока я сделал это, добавив

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

к началу тестовых файлов. В качестве альтернативы можно написать короткий сценарий оболочки, который добавит родительский каталог в PYTHONPATH а затем запустит unittests. Интересно, есть ли лучшие способы справиться с этим?

1 ответ

Взгляните на документы по пути поиска модуля

Когда импортируется модуль со спамом, интерпретатор сначала ищет встроенный модуль с этим именем. Если он не найден, он ищет файл с именем spam.py в списке каталогов, заданных переменной sys.path. sys.path инициализируется из следующих мест:

  • каталог, содержащий входной скрипт (или текущий каталог).
  • PYTHONPATH (список имен каталогов с тем же синтаксисом, что и переменная оболочки PATH).
  • зависящее от установки значение по умолчанию.

Если вы пишете библиотеку, тестовый код должен обычно взаимодействовать с библиотекой так же, как и пользователь библиотеки. Это может означать добавление модуля в путь поиска либо путем установки переменной окружения PYTHONPATH, либо путем установки модуля в местоположении модуля по умолчанию.

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

python -m unittest discover (python >= 2.7)

Это будет рекурсивно искать файлы, соответствующие test_*.py (то есть внутри модулей dirs), но должен установить путь python относительно родительского каталога.

licensed under cc by-sa 3.0 with attribution.