Структура папок Python для каталога проектов и простого импорта
У моей команды есть папка с несколькими небольшими проектами на python3. Среди них есть папка с несколькими утилитами, которые используются в проектах. Но способ импортировать его очень неудобен. Это структура, которую мы используем:
temp_projects
util
storage.py
geometry.py
project1
project1.py
project2
project2.py
Проблема в том, что импорт в проектах выглядит ужасно:
sys.path.insert(1, os.path.join(sys.path[0], '..'))
import util.geometry
util.geometry.rotate_coordinates(....)
Кроме того, pycharm и другие инструменты испытывают проблемы с пониманием этого и поставкой завершенности.
Есть ли более аккуратный способ сделать это?
Изменить: все проекты и утилиты находятся в стадии разработки и часто модифицируются, поэтому я ищу что-то максимально гибкое и удобное
6 ответов
PYTHONPATH
переменная окружения может быть способом пойти. Просто установите его в папку проекта:
PYTHONPATH=/somepath/temp_projects
и вы сможете использовать util
следующее:
import util.geometry
util.geometry.rotate_coordinates(....)
Также это будет распознаваться PyCharm автоматически.
Я считаю, что правильный маршрут будет полностью отличаться от того, что вы делаете сейчас. Каждый проект должен храниться в отдельном репозитории Git, модули общего доступа должны быть добавлены как подмодули git. Как только эти проекты станут более крупными и сложными (и, вероятно, будут), им будет легче управлять ими по отдельности.
Короче
Структура проектов должна быть:
Project_1
|- utils <submodule>
|- storage.py
|- geometry.py
|- main.py
Project_2
|- utils <submodule>
|- storage.py
|- geometry.py
|- main.py
Работа с подмодулями
### Adding a submodule to an existing git directory
git submodule add <git@github ...> <optional path/to/submodule>
### Pulling latest version from master branch for all submodules
git submodule update --recursive --remote
### Removing submodule from project
# Remove the submodule entry from .git/config
git submodule deinit -f path/to/submodule
# Remove the submodule directory from the project's .git/modules directory
rm -rf .git/modules/path/to/submodule
# Remove the entry in .gitmodules and remove the submodule directory located at path/to/submodule
git rm -f path/to/submodule
Дальнейшее чтение https://git-scm.com/book/en/v2/Git-Tools-Submodules
Согласно импорту файлов из другой папки, добавив __init__.py
в папке util вызовет python для обработки его как пакета. Еще одна вещь, которую вы можете сделать, это использовать import util.geometry as geometry
и тогда вы могли бы использовать geometry.rotate_coordinates(...)
что также улучшает читаемость.
Если вы создаете setup.py
файл для вашего util
Модуль вы можете установить его просто с помощью pip. Это будет обрабатывать все для вас. После установки вы можете импортировать его через систему.
import util
установка pip
# setup.py is in current folder
sudo -H pip3 install .
или если util
сам модуль находится в стадии разработки, вы можете установить его с -e
редактируемый вариант. Затем он автоматически обновляет установку при внесении изменений в код.
sudo -H pip3 install -e .
Для администрации проекта рекомендую использовать git
как @Michael Liv. предлагает, особенно если вы работаете в команде.
Используйте importlib.
import importlib, importlib.util
def module_from_file(module_name, file_path):
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
geometry = module_from_file("geometry", "../temp_projects/utils/geometry.py")
geometry.rotate_coordinates(...)
Другой вариант (я использовал этот подход в моем проекте):
Предположим, что проекты запускаются из project1.py
а также project2.py
файлы соответственно.
В верхней части этих файлов вы можете добавить следующие операции импорта и импорта:
import sys
import os
sys.path.append(os.path.join(os.getcwd(), os.pardir))
import your_other_modules
your_other_modules.py будет содержать следующее для наложения утилит
from utils import storage
from utils import geometry
# or from project2 import project2, etc..
Может быть, это не лучший способ, но просто как еще один вариант. Я надеюсь, что это будет полезно для кого-то.