Импорт модулей из соседних пакетов в Python без sys.path.insert
Быстрый ответ
Для импортирования модулей из одного и того же пакета используйте относительные импорты с точками:
# В sibling_package/subpackage2/module2.py
# Позвольте представить вашего "соседа" – module1!
from ..subpackage1 import module1
Альтернативно, вы можете внести изменения в sys.path, добавив родительскую директорию:
import sys
from pathlib import Path
# Разрешите расширить sys.path, добавив в него родительскую директорию.
sys.path.append(str(Path(__file__).resolve().parent.parent))
from subpackage1 import module1
Учтите, что скрипты не стоит запускать напрямую как __main__
– это нарушает работу относительных импортов.
Структурирование проекта: скрипт установки и расположение пакетов
Продуманная структура проекта – залог успешной работы. Рекомендуем выполнить следующие действия:
- Создайте файл setup.py, используя
setuptools.setup()
. Этот файл определит структуру вашего пакета и позволит "расставить все по местам".
# В файле setup.py
# "Вечеринка" начинается с setuptools.setup()!
from setuptools import setup, find_packages
setup(name='your_package', version='1.0', packages=find_packages())
Оформляйте пакеты так, чтобы они были папками вместе с файлом setup.py: файл
__init__.py
указывает Python'у, что здесь разместился валидный пакет для импорта.Установите свой пакет в режиме разработки: команда
pip install -e <path_to_your_project>
позволит обновлять пакет без необходимости повторного его установления.Воспользуйтесь виртуальными окружениями: они эффективно "оберегают" ваши проекты от конфликтов зависимостей, представляя собой своего рода "зоны отдыха" для различных проектов.
Правильный запуск скриптов
Чтобы избежать ошибок при работе с импортами:
- Используйте
python -m
при запуске скриптов, которые представляют собой пакеты.
# В командной строке:
# Давай дерзай, Python, настроимся на "m"!
python -m script
Для тестирования лучше сосредотачиваться на
pytest
– он сам будет управлятьsys.path
.Файл setup.cfg стоит рассматривать как "информационный стенд" проекта, облегчающий его установку для других пользователей.
Импорт внутри пакета: верные пути
Вот некоторые рекомендации по импорту внутри вашего пакета:
Отдавайте предпочтение относительным импортам: они делают структуру вашего пакета более понятной и структурированной.
Следуйте руководству PEP для обеспечения лучшей совместимости между различными версиями Python.
Избегайте изменений в
sys.path.insert
: такие действия могут приводить к проблемам с поддержкой кода.
Визуализация
Представим структуру наглядно:
Здание (🏢): Этажи [1, 2, 3, 4]
Квартира А (🚪): Находится на 2 этаже
Квартира Б (🚪): На 3 этаже
Связь модулей внутри одного пакета выглядит так:
Чтобы перейти из 🚪А в 🚪Б, воспользуйтесь лифтом (🛗) или лестницей (🔼) внутри 🏢.
Суть заключается в следующем:
**Модули одного пакета** типа 🚪А и 🚪Б "проживают" под одной крышей (🏢) и могут без проблем перемещаться друг к другу.
Управление импортами в крупных проектах
Для того чтобы избежать хаоса в "танце импортов" в больших проектах, придерживайтесь следующих методик:
Упрощайте структуру проекта: если в вашем проекте слишком много "комнат", возможно стоит провести его оптимизацию.
Размещайте тесты внутри пакетов: тестовые файлы должны быть легко доступны, ведь это те "участники", с которыми все хотят взаимодействовать.
Отказывайтесь от ненужных файлов
__init__.py
: начиная с Python 3.3, хорошо работают неявные пакеты пространства имен без файлов__init__.py
.
Готовность вашего проекта к будущему
Советы по обеспечению "долгосрочности" вашего проекта:
Создавайте такую структуру каталогов, которая поддерживает осуществление импорта модулей.
Периодически проводите рефакторинг для упрощения путей импорта.
Следите за актуальностью стандартов Python и вносите соответствующие изменения в ваш проект.
Полезные материалы
- Структурирование вашего проекта – Python Developer's Guide
- 6. Модули – Python's Doc 3.12.2
- PEP 328 – Многострочные и абсолютные/относительные импорты
- 5. Система импорта – Python's Doc 3.12.2
- Упаковка проектов Python – Python Packaging User Guide
- Как осуществить относительные импорты в Python? – Stack Overflow
- GitHub – navdeep-G/samplemod