首页 > 解决方案 > Python:基本项目结构和导入路径

问题描述

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

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

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

现在,其中的第一个和第三个似乎没有问题,但我在处理中间的问题时遇到了麻烦。

以下是文件的内容:

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()事情?还是有更好的处理进口的方法?

标签: pythonpython-3.xpytest

解决方案


推荐阅读