Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a clean way to suppress compiler warnings from Cython when using pyximport.install?

Tags:

python

cython

Say I have a simple package of the following structure:

cython_functions/
    __init__.py
    fib.pyx

where fib.pyx contains:

def fib(int n):
    fiblist = [0, 1]
    a, b = fiblist
    while b < n:
        a, b = b, a + b
        fiblist.append(b)
    return fiblist

and __init__.py contains:

import pyximport
pyximport.install()
from cython_functions.fib import fib

If I make any changes to fib.pyx I get a whole bunch of compiler warnings whenever I try to import the package:

/Users/andfranklin/.pyxbld/temp.macosx-10.6-intel-3.5/pyrex/cython_functions/fib.c:1687:28: warning: unused function '__Pyx_PyObject_AsString' [-Wunused-function]
static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
                           ^
/Users/andfranklin/.pyxbld/temp.macosx-10.6-intel-3.5/pyrex/cython_functions/fib.c:1684:32: warning: unused function '__Pyx_PyUnicode_FromString' [-Wunused-function]
static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) {
                               ^
.
.
.

Is there any easy way to suppress them? In another questions they describe how to pass compiler flags through an .pyxbld file. It is possible for me to create fib.pyxbld containing the following:

def make_ext(modname, pyxfilename):
    from distutils.extension import Extension
    return Extension(name=modname,
                     sources=[pyxfilename],
                     extra_compile_args=['-w'])

I would like to avoid this. If I need to create more functions I also need to create more .pyxbld files with the same boilerplate. This seems excessive and un-pythonic.

like image 928
Andrew Franklin Avatar asked Apr 11 '16 19:04

Andrew Franklin


1 Answers

I've battled this exact thing myself (glad to know I'm not alone!) and have not found a perfect solution. Unfortunately pyximport is rather opaque and doesn't AFAICT have much in the way of customizability.

But I do have what I think is a reasonable workaround, which helps especially once you have a growing number of Cython modules.

Basically, I have a module somewhere (let's say common.cython) that contains something like this:

from distutils.extension import Extension


DEFAULT_EXTENSION_KWARGS = {
    "extra_compile_args": ["-w"]
}


def pyx_extension(**kwargs):
    for key, value in DEFAULT_EXTENSION_KWARGS.items():
        if key not in kwargs:
            kwargs[key] = value

    return Extension(**kwargs)


def make_ext(modname, pyxfilename):
    return pyx_extension(name=modname, sources=[pyxfilename])

Basically a thin wrapper around the distutils Extension class, where I can set some custom defaults.

Then next to pyx modules that don't need any custom building, I put a some_module.pyxbld with just one line:

from common.cython import make_ext

This works nicely because the .pyxbld file is just a python module that's expected to contain a make_ext function with that signature.

If I do need to customize the .pyxbld for the module, say if I need to add a C source file or something, it'll look something like this:

def make_ext(modname, pyxfilename):
    from common.cython import pyx_extension

    return pyx_extension(name=modname, sources=[pyxfilename, "my_extra_source.c"])

So, not hugely different from the basic documented way, but just enough to satisfy my DRY OCD :) Hope this helps, and please let me know if you find a better way.

like image 181
Jon Edvald Avatar answered Sep 28 '22 01:09

Jon Edvald