混合C++和Python的项目目录结构

12 投票
1 回答
4733 浏览
提问于 2025-04-18 16:58

假设你想创建一个同时使用 C++Python 的编程项目。这个 FooC++ 项目结构使用 CMake,而 Python 模块是通过 Swig 创建的。它的文件结构大概是这样的:

├── CMakeLists.txt
├── FooConfig.cmake.in
├── FooConfigVersion.cmake.in
├── Makefile
├── README
├── foo
│   ├── CMakeLists.txt
│   ├── config.hpp.in
│   ├── foo.cpp
│   └── foo.hpp
└── swig
    └── foo.i

现在你想在一个 Python 项目中使用 Foo 项目,比如叫做 Bar

├── AUTHORS.rst
├── CONTRIBUTING.rst
├── HISTORY.rst
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.rst
├── docs
│   ├── Makefile
│   ├── authors.rst
│   ├── conf.py
│   ├── contributing.rst
│   ├── history.rst
│   ├── index.rst
│   ├── installation.rst
│   ├── make.bat
│   ├── readme.rst
│   └── usage.rst
├── bar
│   ├── __init__.py
│   └── bar.py
├── requirements.txt
├── setup.cfg
├── setup.py
├── tests
│   ├── __init__.py
│   └── test_bar.py
└── tox.ini

这个结构是通过 cookiecutter 的 pypackage 模板 创建的。还有一个 BoilerplatePP 模板可以用来生成一个 CMakeC++ 项目(没有 Swig 部分)。所以现在我有了两个项目的结构,并且考虑到开发主要会在 Python 中进行,项目会在不同的系统上运行,我需要考虑以下几个问题:

  1. 混合这两个项目的最佳方式是什么?我应该把两个根目录合并吗?应该把 FooC++ 项目放在 Bar 项目的目录里,还是反过来?我可能倾向于把上面显示的整个 C++ 结构放在 Python 项目根目录的一个文件夹里,但我想提前了解可能的坑,因为 CMake 系统非常强大,可能反过来做会更方便。
  2. 如果我决定把 Foo 项目放在 Bar 的一个目录里,Python 的 setuptools 包是否和 CMake 的构建系统一样强大?我问这个是因为当我查看 Bar 项目时,顶层似乎只有一堆脚本,但我不知道这是否相当于 CMake,因为我对 Python 还不太熟悉。
  3. 上面提到的 Bar 项目只有一个 bar 目录,但我假设当这个项目扩展时,不会在根目录下有很多其他目录,而是会在 bar 里放置其他包含 Python 代码的目录。这是正确的吗(从 Pythonic 的角度来看)?
  4. 我假设整个项目会生成一个单一的 egg,这样可以在许多不同的 Python 系统中安装和运行。由 Foo 项目创建的模块集成起来容易吗?我假设这个模块会在一个不同于 bar 的目录中创建。
  5. 为了让 bar 目录中的 Python 代码能够使用,由 Swig 创建的模块必须可用,所以我想最简单的方法是通过 CMake 系统修改环境变量 PYTHONPATH。这样做可以吗,还是有更好的方法?

1 个回答

8

如果这个C++程序只会在包含它的Python包中使用:

你可以把C++代码放在属于它的Python包里,这样做比较安全。比如在你的例子中,可以在“bar”目录下再放一个“foo”目录。这样打包最终的Python模块会简单一些。

如果这个C++程序是可以重复使用的:

我建议你考虑把东西分成“包”,也就是把独立的部分放在一起,每个部分都是自成一体的。所有独立的部分都放在同一层级。如果某个部分需要依赖另一个部分,你就从同一层级的对应“包”中导入。这就是依赖关系通常是怎么运作的。

我不会把一个包放在另一个包里面,因为它们并不严格属于同一个包。假设你开始了第三个项目,需要“foo”,但不需要“bar”,那就麻烦了。

我会把“foo”和“bar”这两个包放在同一个“项目”目录下(而且我可能会给每个包单独建立一个代码仓库,这样每个包就能更方便地维护和安装)。

撰写回答