Структура папок 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..

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

Другие вопросы по тегам