Python: базовая структура проекта и пути импорта - PullRequest
0 голосов
/ 08 июня 2019

Для моего проекта Python 3 у меня есть следующая структура каталогов:

├── myapp
│   ├── compute
│   │   └── compute.py
│   └── mymain.py
├── setup.py
└── tests
    └── compute
        └── compute_test.py

Моя цель состоит в том, чтобы иметь возможность выполнить код здесь тремя способами:

  • Unitтесты.Я случайно выбрал pytest для них, но какой бы ни был фреймворк;
  • python myapp/mymain.py <arguments> для того, когда я хочу сделать быстрый "ручной тест";
  • Что-то вроде pip installи / или образ Docker для правильного развертывания.

Теперь, первый и третий из них, похоже, не проблема, но у меня проблемы с серединой.

Вот содержимое файлов:

compute.py:

import math


class MyComputation:

    # performs an extremely difficult and relevant computation
    @staticmethod
    def compute(i: int) -> float:
        return math.sqrt(abs(i))

compute_test.py:

import pytest

from myapp.compute.compute import MyComputation


def test_computation_normal_case():
    ins = [-4, 9, -36, 121]
    outs = list(map(lambda i: MyComputation.compute(i), ins))
    expected = [2.0, 3.0, 6.0, 11.0]
    assert outs == expected

mymain.py:

import random

from myapp.compute.compute import MyComputation


class MyApp:

    @staticmethod
    def main():
        print("Loading data...")
        i = random.randint(1, 100000)
        print("Input:  {}".format(i))
        print("Computing...")
        f = MyComputation.compute(i)
        print("Output: {}".format(f))
        print("Done!")


if __name__ == "__main__":
    MyApp.main()

Когда я запускаю, скажем, pytest из командной строки, он работает нормально: находит тест, запускает его, тест проходит.

Однако, когда я пытаюсь запустить основной класс:

$ python myapp/mymain.py 
Traceback (most recent call last):
  File "myapp/mymain.py", line 8, in <module>
    from myapp.compute.compute import MyComputation
ImportError: No module named myapp.compute.compute

Не имеет значения, добавляю ли я __init__.py файлы в каталоги или нет.

Но если я добавлю следующее в mymain.py, его можно будет запустить из командыстрока, как и ожидалось:

import os
import sys

root_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), '../'))
sys.path.insert(0, root_path)

Итак, вопросы:

1) Как правильно, Pythonic, идиоматический способ сделать основной класс?По сути, я хочу «запустить этот код здесь, на месте, как есть».Где я могу поставить свой основной класс?Нужно ли мне pip install мои вещи сначала локально?Нужно ли делать импорт по-другому?

2) Конечно, материал sys.path.insert() не может быть "официальным" способом выполнения того, что я хочу сделать здесь?Должен быть менее нелепый способ ... верно?

3) Почему юнит-тесты работают просто отлично, а основной класс - нет?Есть ли в модуле модульного тестирования что-то похожее на sys.path.insert() под крышками?Или есть лучший способ обработки импорта?

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