Python:基本项目结构和导入路径

时间:2019-06-08 00:30:37

标签: python python-3.x pytest

对于我的Python 3项目,我具有以下目录结构:

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

我的目标是能够以三种方式在此处运行代码:

  • 单元测试。我为此随机选择了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()的操作?还是有更好的方式处理进口商品?

0 个答案:

没有答案