如何从Python中断言C代码?

7 投票
3 回答
1883 浏览
提问于 2025-04-16 09:05

我正在用C语言写一个Python类,想在调试代码中加入一些断言。assert.h这个头文件正好适合我。因为它只会在调试版本中使用,所以不会影响到使用这个Python代码的用户。

我想把我的“库”代码和链接到Python的代码分开,这样我就可以在其他C代码中使用它。因此,我的Python方法其实就是对我纯C代码的一个简单封装。

所以我不能在我的“库”代码中这样做:

if (black == white)
{
    PyErr_SetString(PyExc_RuntimeError, "Remap failed");
}

因为这样会把我的纯C代码和Python混在一起。而且这样看起来也比一个简单的

assert(black != white);

要丑得多。我相信Distutils编译器总是会设置NDEBUG,这意味着即使在调试版本中我也不能使用assert.h

我在使用Mac OS和Linux。

求助!

*这是我听说过的一个反对在C代码中使用断言的理由,因为这些代码是从Python调用的。

3 个回答

2

你可以自己创建一个宏,比如 myassert(),用来处理不同的情况。或者你也可以创建一个宏,它会检查一个全局变量,看看这个宏是从Python代码里用的,还是从“普通”的C代码里用的。这样的话,Python模块的入口点就需要把这个变量设置为真,或者你可以使用函数指针,一个指向Python代码,另一个默认指向C代码。

3

在你的 setup.py 文件中取消定义 NDEBUG 这个宏:

ext_modules = [Extension(
    ...
    undef_macros=['NDEBUG'],
)]

这样会在命令行中出现类似下面的内容:

gcc ... -DNDEBUG ... -UNDEBUG ...

虽然看起来不太好,但这样做是对的,也就是说,它会保持断言功能开启。

8

只需要使用 assert.h 这个头文件就可以了。关于 distutils 总是定义 NDEBUG 的说法其实是个误解;它只在 Windows 系统上针对微软的 msvc 编译器时才会这样做,而且只有在你从 Python 的发布版本构建时才会定义(而不是从 Python 的调试版本构建时)。

如果你想在自己的发布版本中定义 NDEBUG,可以在运行 setup.py build_ext 时,给命令行加上 -D 这个选项。

补充说明:看起来 NDEBUG 是通过 Python 的 Makefile 中的 OPT 设置默认定义的。如果想要重置这个设置,可以运行

OPT="-g -O3" python setup.py build

撰写回答