How can I assert from Python C code?
Asked Answered
R

3

7

I'm writing a Python class in C and I want to put assertions in my debug code. assert.h suits me fine. This only gets put in debug compiles so there's no chance of an assert failure impacting a user of the Python code*.

I'm trying to divide my 'library' code (which should be separate to the code linked against Python) so I can use it from other C code. My Python methods are therefore thinnish wrappers around my pure-C code.

So I can't do this in my 'library' code:

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

because this pollutes my pure-C code with Python. It's also far uglier than a simple

assert(black != white);

I believe that the Distutils compiler always sets NDEBUG, which means I can't use assert.h even in debug builds.

Mac OS and Linux.

Help!

*one argument I've heard against asserting in C code called from Python.

Ribaldry answered 27/12, 2010 at 20:24 Comment(0)
M
8

Just use assert.h. It's a myth that distutils always defines NDEBUG; it only does so for Microsoft's msvc on Windows, and then only when invoked from a Python release build (not from a Python debug build).

To then define NDEBUG in your own release builds, pass a -D command line option to setup.py build_ext.

Edit: It seems that NDEBUG is defined by default through Python's Makefile's OPT setting. To reset this, run

OPT="-g -O3" python setup.py build
Melodymeloid answered 27/12, 2010 at 20:51 Comment(3)
That's what I want to hear! So, when I run python setup.py build or python setup.py build --debug I get something like: gcc-4.2 -fno-strict-aliasing -fno-common -dynamic -arch i386 -arch x86_64 -g -O2 -DNDEBUG -g -O3 -g -UDEBUG -I/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c thing.c -o build/temp.macosx-10.6-intel-2.7/thing.o. How would I remove the NDEBUG?Ribaldry
That doesn't really solve the problem. It's not a good solution to tell all your users to use a custom build command if you want to enable asserts in all cases. This needs to be fixed somehow in a clean way in setup.py.Gnome
OPT did not work for me (Py3, setuptools), however CFLAGS did: CFLAGS="-O0 -UNDEBUG" python3 setup.py build_ext -iZorina
B
3

Undefine the NDEBUG macro in your setup.py:

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

This will result in a command line like

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

Which (while ugly) does the correct thing, i.e. it keeps assertions enabled.

Baffle answered 15/1, 2015 at 2:28 Comment(0)
H
2

Create your own macro, such as myassert() for different situations. Or create a macro, which checks a global variable to see if the macro is used from Python code or "normal" C. The Python module entry point would have to set this variable to true, or you could use function pointers, one for Python code, another default one for C code.

Handgrip answered 27/12, 2010 at 20:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.