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.

3 Answers 3

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
Sign up to request clarification or add additional context in comments.

3 Comments

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?
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.
OPT did not work for me (Py3, setuptools), however CFLAGS did: CFLAGS="-O0 -UNDEBUG" python3 setup.py build_ext -i
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.

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.