C++开发(五)
C++和Python开发(五)
最后整理些细碎的内容,就把和GPT的聊天都删掉了,最近在这些上投入了太多精力,需要做些其他事情缓解一下了。
Pytest
pytest
中的tests
目录下可以新建一个conftest.py
文件,不同的test_xx.py
都会先运行这个文件,类似于GoogleTest中的夹具。
import
Python的import
确实还有很多地方我没弄明白。from xx import yy
中,xx
必须是一个实际存在的东西,不论是一个目录(包)还是一个文件(模块),纯粹导入命名空间是不行的。
setup
可以通过环境变量,让用户自行决定是否安装某些扩展模块。这可以通过扩展build_ext
来实现:
1 | class CMakeBuild(build_ext): |
pip和python setup.py
pip install .
- 依赖管理:
pip
会自动管理依赖关系,并确保所有依赖项都被正确安装。如果你的项目中定义了install_requires
选项(在setup.py
中),pip
会确保这些依赖项在安装你的包之前被安装。 - 使用
wheel
包: 如果可能,pip
会尝试使用已经构建好的wheel
文件(.whl
)来安装包,这通常比从源码构建快得多。如果没有现成的wheel
,pip
也可以从源码构建并安装。 - 隔离环境: 默认情况下,
pip
会使用一个临时的隔离环境来执行构建,这意味着构建过程中使用的依赖项不会污染全局的Python环境。可以通过--no-build-isolation
选项来禁用这一行为。 - 自动安装
setuptools
和wheel
:pip
会自动确保setuptools
和wheel
这些构建工具已经安装。 - 更多高级功能:
pip
提供了许多额外的功能,比如--upgrade
(升级已安装的包)、--target
(指定安装目录)等。
python setup.py install
- 手动安装: 直接调用
setup.py
的install
命令,不会管理依赖项。这意味着你需要手动确保所有依赖项都已经安装。 - 不使用
wheel
:setup.py install
直接从源码构建并安装包,而不是使用wheel
文件。因此,安装速度可能会更慢,尤其是对于需要编译的扩展模块。 - 无隔离环境:
setup.py install
不会在隔离的环境中运行,所有构建和安装操作都直接在当前的 Python 环境中进行。这可能会导致依赖项之间的冲突,或者污染全局的 Python 环境。 - 逐步过时:
python setup.py install
的使用在逐渐减少,因为pip
提供了更多的功能和更好的依赖管理。官方文档也建议使用pip
来进行安装。
关于inplace
当运行 python setup.py build_ext
来构建 Cython 模块后,生成的 .pyd
(Windows)或 .so
(Linux/Mac)文件通常会被放置在一个特定的构建目录中。默认情况下,这些文件可能并没有直接放在你的源代码目录中,而是被放置在一个名为 build
的子目录里。
查看
build
目录:默认情况下,构建的模块通常位于
build/lib.<platform>
目录下。例如,在 Windows 上可能是build/lib.win-amd64-3.8
(假设你使用的是 Python 3.8)。你可以使用以下命令来查看构建目录:
1
ls build/
使用
--inplace
选项:如果你希望生成的模块直接放在源代码目录(与
.pyx
文件相同的目录)中,可以在运行build_ext
时使用--inplace
选项:1
python setup.py build_ext --inplace
这样生成的
.pyd
文件将直接出现在源代码目录中,与你的.pyx
文件在同一个位置。
指定构建目录:
- 如果你希望构建的模块放在一个特定的目录中,可以在
setup.py
中使用ext_modules
和Extension
类的参数build_dir
来指定。
- 如果你希望构建的模块放在一个特定的目录中,可以在
关于cython构建
cython的构建比较麻烦,在命令行里直接用cythonize
,至少在Win下很难导入Numpy的头文件。在setup.py
里改写build_ext
的run
方法,cython的构建就会一直出错。现在看来比较好的方式就是,ext_modules
中只放置cython的模块,重写build_ext
后,调用super().run()
,保证cython模块的正常构建。其他模块则在之后cmake手动构建,但这些模块都不放入到ext_modules
中。构建出来的文件,不需要手动改写RECORD
文件注册,直接放到对应的package_data
参数中就可以了。这样的方式目前来看是可行的,而且干净的。
关于相对导入
Python的相对导入只能是一个大包下面的包或者模块间相对导入,外部包间是不支持的。