Подмодуль Python C-extension Ошибка: нет модуля с именем "x" - PullRequest
0 голосов
/ 02 мая 2018

У меня проблемы с созданием C-расширения в качестве подмодуля в моем коде. Расширение C ниже компилируется просто отлично. Проблема возникает, когда я пытаюсь добавить его в другой модуль.

Вот код C: Имя файла prctl3-0.c. Я могу получить компиляцию для Python2.7 и Python 3.0.

#include <Python.h>

#include <stdio.h>
#include <string.h>
#include <sys/prctl.h>

// Now we need to identify which version of Python we are working with.
//  For backwards compatibility, we need to be able to be compiled by either
//  Python 2.7 or Python3.x.

#if PY_MAJOR_VERSION >=3
#define PY_3CODE            // We will use this pre-compile statement to differentiate
                            //  between code for Py2.7 and 3.x
#endif

/* osCall_changeName
  Calls prctl() to change the name of the calling thread, process or subprocess

*/
static PyObject* osCall_changeName(PyObject*self, PyObject* args)
{
  const char *passedInName;   // Name passed in by the system
  size_t nameLength;          // Calculated by calling strlen() on passedInName

  char newName[16];           // In Python newName= passedInName[0:15]+ \0
  int nameChangeRes;          // stores error code for calling prctl()

  PyObject *retName;          // Return value; Python None if error occurs

  // Check if argument passed in successfully
  if(! PyArg_ParseTuple(args, "s", &passedInName)){
    printf("Error in arg passing\n");
    Py_RETURN_NONE;
  }

  nameLength = strlen(passedInName);
  if( nameLength > 15){       // prctl() automatically truncates, but unsure if new string is null-terminated
     strncpy(newName, passedInName, 15);
     newName[15] = '\0';
  } else {
    strcpy(newName, passedInName);
  }

  //Actual function call
  nameChangeRes = prctl(PR_SET_NAME, newName, 0,0,0);

  if( nameChangeRes == 0 )    // Success; pass back the changed name value
  {
    retName = Py_BuildValue("s", newName);
    return retName;
  }

  // Method failed; return None
  Py_RETURN_NONE;
}

static PyObject* osCall_getName(PyObject* self) {

  char procName[16];          // Buffer to put prctl results into
  int  nameRetrieveRes;       // Result of the name retrieval operation
  PyObject *retName;          // Python object to return values


  nameRetrieveRes = prctl(PR_GET_NAME, procName, 0,0,0);

  if ( nameRetrieveRes == 0 ) //
  {
      retName = Py_BuildValue("s", procName);
      return retName;
  }
  printf("Process name change failed\n");
  // Operation failed; return None
  Py_RETURN_NONE;
}

//==========================================================
//  STEP 2: COMPILE THE PIECES NEEDED FOR EITHER 2.7 OR 3.X
//    PYTHON LIBRARIES
//==========================================================

static PyMethodDef proc_OsFunc[] = {
  { "changeName",
  (PyCFunction)osCall_changeName,
  METH_VARARGS,
  "Function to give Python process a new associated string ID"},

  { "getName",
  (PyCFunction)osCall_getName,
  METH_NOARGS,
  "Function to get Python process's current string ID"
  },

  {NULL, NULL, 0, NULL} //function array terminator
};

#ifdef PY_3CODE
static struct PyModuleDef osCallDefine = {
  PyModuleDef_HEAD_INIT,
  "prctl3_0",
  "A simple library for accessing prctl() on Linux from Python 3.0",
  -1,
  proc_OsFunc
};

#endif

#ifdef PY_3CODE
// Python 3.0 initialization syntax
PyMODINIT_FUNC PyInit_prctl3_0(void)
{
  Py_Initialize();

  return PyModule_Create(&osCallDefine);
}

#else
// Python 2.0 initialization syntax
PyMODINIT_FUNC initprctl3_0() {
  Py_InitModule3("prctl3_0",proc_OsFunc,
        "A simple library for accessing prctl() on Linux from Python 2.0");
}



#endif

Я надеюсь иметь этот код в имени модуля mpIPC как часть более крупного проекта. У меня проблема, когда я помещаю его в модуль большего размера и пытаюсь получить к нему доступ, используя следующий код, я получаю следующее:

>>> import mpIPC.prctl3_0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named prctl3_0

Мой setup.py файл выглядит следующим образом:

from setuptools import setup, find_packages, Extension

prctl_module = Extension("mpIPC.prctl3_0",
                                sources = ["mpIPC/prctl3_0.c"])

setup(name = "mpIPC",
    version = '0.0',
    description = "Python C module for accessing Linux commands for IPC",
    packages = ['mpIPC'],
    ext_modules = [prctl_module] )

Моя файловая директория для этого модуля:

project/
+- setup.py
+- mkdir/
-+- __init__.py 
-+- prctl3_0.c
-+- os.py   # used for other Linux os calls

Я не совсем уверен, чего мне не хватает. Я также проверил следующую ссылку: Как создать расширение Python C, чтобы я мог импортировать его из модуля но это не очень помогает мне на этом этапе.

1 Ответ

0 голосов
/ 02 мая 2018

Я получил его без каких-либо модификаций исходного кода.

  1. Ваш каталог "mkdir" должен иметь имя "mpIPC", которое является именем модуля. Вы хотите, чтобы ваша структура каталогов была похожа внизу

  2. делать не пытаться проверить это из вашей директории с исходным кодом, то есть нигде из project, поскольку это попытается импортировать, согласно структуре модуля Python, из директории "mpIPC" (который вы создадите в 1)) (кредит для этой подсказки идет к этому комментарию в сообщении, которое вы упомянули . Вместо этого, попробуйте его, например, из любого места в вашем домашнем каталоге. есть, если вы сначала запустили python setup.py install :)

Дерево каталогов:

foobar
    ├── mpIPC
    │   ├── __init__.py
    │   ├── os.py
    │   └── prctl3_0.c
    └── setup.py
...