简体   繁体   中英

How do I use setuptools to create a python package with multiple modules?

I want to organize a distribution with several modules. Eventually there will be a C extension module, and at the same 'level', several pure python modules. I am not sure whether the top level should just be considered a namespace.

For starters, I would like to create a module monty.spam. It will be a C extension. I lifted this out of the Extending Python docs.

monty/spam/spammodule.c

#include <Python.h>

static PyObject * spam_system (PyObject * self, PyObject * args)
  {
  const char * command;
  int          sts;

  if (!PyArg_ParseTuple (args, "s", &command))
    return NULL;
  sts = system (command);
  return Py_BuildValue ("i", sts);
  }

static 
PyMethodDef SpamMethods [] = {
             { "system", spam_system, METH_VARARGS, "Execute a shell command" },
             { NULL, NULL, 0, NULL }    
             };

PyMODINIT_FUNC
initspam (void)
  {
  (void) Py_InitModule ("spam", SpamMethods);
  }

I created a setup tools setup.py in the same directory, ran "python setup.py develop" and the module worked fine.

monty/spam/setup.py

from setuptools import setup, Extension

module = Extension ('spam', sources = [ 'spammodule.c' ])

setup (
      name = 'MontyP',
      version = '0.2', 
      description = 'pure spam',
      ext_modules = [ module ]
      )

In the monty directory:

python -c 'import monty.spam'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named monty.spam

So now I would like to create a distribution in which spam "lives in" monty. I have tried a number of variations on the setup.py them in the monty directory. (Both directories have an empty __init__.py )

My latest try at monty/setup.py: (yes, the find_packages () has no utility in this version.)

from setuptools import setup, Extension, find_packages

module = Extension ('spam', sources = [ './spam/spammodule.c' ])

print find_packages ()
setup (
      name               = 'MontyP',
      version            = '0.2', 
      namespace_packages = [ 'monty' ],
      packages           = find_packages (),
      description        = 'pure spam',
      ext_modules        = [ module ]
      )

No Joy!

python setup.py develop
['spam']
error in MontyP setup command: Distribution contains no modules or packages for namespace package 'monty'

You just need two or three changes to make it work.

First, instead of placing it at monty/spam , setup.py should be placed in the same level as monty/ :

在此输入图像描述

setup.py always goes in the root of the project.

Also, create an __init__.py file in monty but no __init__.py inside spam .

Now, in setup.py , in the line " module = Extension ('spam', sources = [ 'spammodule.c' ]) ", replace spam by monty.spam and spammodule.c by monty/spam/spammodule.c :

module = Extension ('monty.spam', sources = [ 'monty/spam/spammodule.c' ])

This is necessary because external modules should be declared with their full names ( monty.spam instead of spam ). Also, since now setup.py is in the root of the project, it should receive a relative but complete path to the C source file.

That's it, your module should work now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM