使用 __init__.py 导入 Python 包的目录结构

Directory Structure for Importing Python Package using __init__.py

我有一个 python 项目 (projectA),我已将其作为 git 子模块包含在单独项目 (projectB) 的子文件夹中。结构布局为

projectB/
  projectB_file.py
  projectA/        (repository)
    projectA/      (source code)
      module1/
        file1.py   (contains Class1)
      file2.py     (contains Class2)
    tests/
      test_file1.py

我正在尝试弄清楚如何布局 __init__.py 文件,以便在 projectB_file.py 中我可以将 Class1Class2 导入为

from projectA.module1 import Class1
from projectA import Class2

您需要在每个要作为包处理的子目录中有一个 __init__.py。在你的情况下,这意味着一个:

  • projectA
  • projectA/projectA
  • projectA/projectA/module1
  • projectA/projectA/tests

如果你能失去第一个 projectA 文件夹肯定更好。

我认为导入的顶级 projectA 部分是错误的。这将要求您使用 projectA 重复编写导入(例如 import projectA.projectA.module1.file1)。

相反,您应该以某种方式将顶部 projectA 文件夹添加到模块搜索路径(作为 projectB 安装脚本的一部分,或者使用 [=22] 中的设置=]).这样,projectA 作为 top-level 名称将引用内部文件夹,您实际上打算将其作为 projectA 包。

这是一个恼人的问题。我使用的主要方法是编辑 PYTHONPATH。这基本上就是我的做法。

ProjectB/                   # Main Repository
    projectb/               # Package/library
        __init__.py
        projectB_file.py
    docs/
    tests/
    setup.py                # Setup file to distribute the library
    freeze.py               # CX_Freeze file to make executables

    ProjectA/               # Subrepository
        projecta/           # Package/library
            __init__.py
            projectA_file.py
            file2.py
            submodule/
                __init__.py
                file3.py
        pa_module1/         # Additional package/library in 1 project
            __init__.py
            file1.py
        docs/
        tests/
        setup.py

使用此设置,我必须在 运行 ProjectB 的代码之前编辑 python 路径。我使用这种结构,因为它更容易部署和分发。子存储库有助于跟踪 ProjectB 的每个版本的 ProjectA 版本。

cd ProjectB
export PYTHONPATH=${PWD}:${PWD}/ProjectA
python projectb/projectB_file.py

projectB_file.py

from projecta import projectA_file

这是我的开发环境。对于发布环境,有人会使用以下代码进行安装。

# Need a correct setup.py to handle 2 packages for pa_module1 and projecta
pip install ProjectA (install projecta to site-packages) 
cd ..
pip install ProjectB (install projectb to site-packages)

这意味着 projectb 和 projecta 在站点包中。从那里任何文件都可以简单地

from projectb import projectB_file
from projecta import projectA_file, file2
from pa_module1 import file1

# Personally I don't like imports that use project.sub.sub.sub ...
# I have seen it cause import confusion and problems, but it is useful in some situations.
from projecta.submodule import file3

#import projecta.projectA_file
#import projecta # if __init__.py has import code

file1.Class1()
file2.Class2()
file3.Class3()

此外,使用 pip,您可以安装一个库作为开发环境,它链接到真实的项目目录,而不是将文件复制到 site-packages。

pip install -e ProjectA