9

I would like to gather multiple Python modules under one package, so they do not reserve too many names from global set of python packages and modules. But I have problems with modules that are written in C.

Here is a very simple example, straight from the official Python documentation. You can find it at the bottom of the page from here: http://docs.python.org/distutils/examples.html

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foopkg.foo', ['foo.c'])],
      )

My foo.c file looks like this

#include <Python.h>

static PyObject *
foo_bar(PyObject *self, PyObject *args);

static PyMethodDef FooMethods[] = {
    {
        "bar",
        foo_bar,
        METH_VARARGS,
        ""
    },
    {NULL, NULL, 0, NULL}
};

static PyObject *
foo_bar(PyObject *self, PyObject *args)
{
    return Py_BuildValue("s", "foobar");
}

PyMODINIT_FUNC
initfoo(void)
{
    (void)Py_InitModule("foo", FooMethods);
}

int
main(int argc, char *argv[])
{
    // Pass argv[0] to the Python interpreter
    Py_SetProgramName(argv[0]);

    // Initialize the Python interpreter.  Required.
    Py_Initialize();

    // Add a static module
    initfoo();

    return 0;
}

It builds and installs fine, but I cannot import foopkg.foo! If I rename it to just "foo" it works perfectly.

Any ideas how I can make the "foopkg.foo" work? For example changing "foo" from Py_InitModule() in C code to "foopkg.foo" does not help.

2 Answers 2

6

There must be an __init__.py file in the foopkg folder, otherwise Python does not recognize as a package.

Create a foopkg folder where setup.py is, and put an empty file __init__.py there, and add a packages line to setup.py:

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      packages=['foopkg'],
      ext_modules=[Extension('foopkg.foo', ['foo.c'])],
      )
Sign up to request clarification or add additional context in comments.

1 Comment

That did the trick! Thanks :) Although I still think that should have been mentioned in the Python docs :/
1

distutils will be deprecated since python 3.10 , instead you can use setuptools, which is an enhanced alternative of distutils , so you don't need to pass packages argument in your setup(). For example :

from setuptools import setup, Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foopkg.foo', ['foo.c'])],
      )

Then build and install your C extension

python /PATH/TO/setup.py install

After building your C extension successfully, test whether it can be imported as expected by running this command:

python -c "from foopkg import foo"

[side note] One more thing about setuptool is that you can uninstall the C extension package by simply running pip uninstall, for example : python -m pip uninstall foobar

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.