2

想象一下这个项目结构:

myproject
|-- mypkg1
|   |-- __init__.py
|   |-- __main__.py
|   |-- mod1.py
|   |-- mod2.py
|   |-- standalone.py
|
|-- mypkg2
|   |-- __init__.py
|   |-- mod1.py
|   |-- mod2.py
|
|-- tests
|   |-- mypkg1
|   |   | --mod1_test.py
|   |-- mypkg1_mod1_test.py
|
|-- mypkg1_run.py
|-- standalone_run.py
|-- conftest.py
|-- README

使用这些文件内容:

mypkg1.__init__.py

import sys
import inspect
from pathlib import Path

sys.path.append(str((Path(inspect.getfile(inspect.currentframe())) / '../..').resolve()))

mypkg1.__main__.py

from .mod1 import mod1_msg
from .mod2 import mod2_msg
from mypkg2 import mod1, mod2

def main():
    print("Hello from mypkg1 main!")
    print(mod1_msg())
    print(mod2_msg())
    print(mod1.mod1_msg())
    print(mod2.mod2_msg())

if __name__ == '__main__':
    main()

mypkg1.mod1.py

def mod1_msg():
    return "Hello from mypkg1.mod1!"

mypkg1.mod2.py

from .mod1 import mod1_msg

def mod2_msg():
    return "Hello from mypkg1.mod2 and {}".format(mod1_msg())

mypkg1.standalone.py

from .mod2 import mod2_msg

def main():
    print("Hello from mypkg1.standalone!")
    print(mod2_msg())

if __name__ == '__main__':
    main()

mypkg2.__init__.py

import sys
import inspect
from pathlib import Path

sys.path.append(str((Path(inspect.getfile(inspect.currentframe())) / '../..').resolve()))

mypkg2.mod1.py

def mod1_msg():
    return "Hello from mypkg2.mod1!"

mypkg2.mod2.py

from .mod1 import mod1_msg

def mod2_msg():
    return "Hello from mypkg2.mod2 and {}".format(mod1_msg())

tests.mypkg1.mod1_test.pytests.mypkg1_mod1_test.py

from mypkg1.mod1 import mod1_msg

def test_mod1():
    assert mod1_msg() == "Hello from mypkg1.mod1!" 

mypkg1_run.py

from mypkg1.__main__ import main  

if __name__ == '__main__':
    main()

独立运行.py

from mypkg1.standalone import main

if __name__ == '__main__':
    main()

一般存储库要求

  1. mypkg1 可以使用来自 mypkg2 的脚本。
  2. mypkg1 应该可以作为独立包运行。
  3. Pytest 用于测试。

必需的使用行为

  1. 从 myrepo 目录运行包: python -m mypkg1
  2. 从 myrepo 目录外部运行包: python -m [some path].myrepo.mypkg1
  3. 从 myrepo 目录运行独立包脚本: python -m mypkg1.standalone
  4. 从外部 myrepo 目录运行独立包脚本: python -m [some path].myrepo.mypkg1.standalone

所需的测试行为

  1. 从 myrepo 目录调用 pytest 应该收集并运行测试文件夹中的所有测试
  2. mypkg1_mod1_test.py 和 mod1_test.py 应该可以从其父目录运行
  3. mypkg1_mod1_test.py 和 mod1_test.py 应该可以从任何外部目录运行

结论

  1. 由于需要从 myrepo 外部的路径运行包,因此需要相对导入。
  2. 此行是查找兄弟包所必需的 sys.path.append(str((Path(inspect.getfile(inspect.currentframe())) / '../..').resolve()))

最后是我的问题

  1. 有没有办法让standalone.py在这个项目结构中作为脚本从它的包中运行?就像双击脚本文件一样。当我像这样独立运行时,出现此错误: ModuleNotFoundError: No module named '__main__.mod2'; '__main__' is not a package 此错误是由包中的相对导入引起的。
  2. 我的项目/包结构约定中是否有任何反模式?
  3. 有什么需要纠正或改进的地方吗?
4

0 回答 0