如何从Python中断言C代码?
我正在用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 个回答
你可以自己创建一个宏,比如 myassert()
,用来处理不同的情况。或者你也可以创建一个宏,它会检查一个全局变量,看看这个宏是从Python代码里用的,还是从“普通”的C代码里用的。这样的话,Python模块的入口点就需要把这个变量设置为真,或者你可以使用函数指针,一个指向Python代码,另一个默认指向C代码。
在你的 setup.py
文件中取消定义 NDEBUG 这个宏:
ext_modules = [Extension(
...
undef_macros=['NDEBUG'],
)]
这样会在命令行中出现类似下面的内容:
gcc ... -DNDEBUG ... -UNDEBUG ...
虽然看起来不太好,但这样做是对的,也就是说,它会保持断言功能开启。
只需要使用 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