在 C 中将 Cython 模块构建为 运行 - ModuleNotFoundError
Building Cython module to run in C - ModuleNotFoundError
我有一个 Cython 模块,我想在 C 中调用 运行,但我收到 ModuleNotFound 错误。据我所知,我正在按照文档和其他 SO 问题中的说明进行操作,但是除了简单的 1 文件示例(即非模块化)之外,使用 Cython 将 Python 转换为 C 的示例有限。
我在 Ubuntu 上 运行ning Python 3.6(通过 Windows 10 WSL1)。
这是一个显示问题的简化示例:
树:
├── Makefile
├── main.c
├── main_cy.pyx
├── mod_dir
│ ├── __init__.pxd #empty
│ ├── mod.pxd
│ └── mod.pyx
└── setup_cy.py
mod_dir/mod.pxd:
cdef public int say_hello_from_mod() except -1
mod_dir/mod.pyx:
TEXT_TO_SAY = 'Hello from Python!'
cdef public int say_hello_from_mod() except -1:
print(TEXT_TO_SAY)
return 0
main_cy.pyx:
print('hello from main_cy')
from mod_dir.mod cimport say_hello_from_mod
cdef public int say_hello_from_main_cy() except -1:
say_hello_from_mod()
return 0
main.c:
#include "main_cy.h"
int main(int argc, char *argv[])
{
PyObject *pmodule;
wchar_t *program;
program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0], got %d arguments\n", argc);
exit(1);
}
/* Add a built-in module, before Py_Initialize */
if (PyImport_AppendInittab("main_cy", PyInit_main_cy) == -1) {
fprintf(stderr, "Error: could not extend in-built modules table\n");
exit(1);
}
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(program);
/* Initialize the Python interpreter. Required. If this step fails, it will be a fatal error. */
Py_Initialize();
/* Optionally import the module; alternatively, import can be deferred until the main_cy script imports it. */
pmodule = PyImport_ImportModule("main_cy");
if (!pmodule) {
PyErr_Print();
fprintf(stderr, "Error: could not import module 'main_cy'\n");
goto exit_with_error;
}
printf("Hello from C!\n");
/* Now call into your module code. */
if (say_hello_from_main_cy() < 0) {
PyErr_Print();
fprintf(stderr, "Error in Python code, exception was printed.\n");
goto exit_with_error;
}
/* Clean up after using CPython. */
PyMem_RawFree(program);
Py_Finalize();
return 0;
/* Clean up in the error cases above. */
exit_with_error:
PyMem_RawFree(program);
Py_Finalize();
return 1;
}
setup_cy.py:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize(['mod_dir/mod.pyx', 'main_cy.pyx'], annotate=False,language_level=3, include_path=['./', './mod_dir/'])
)
生成文件:
all:
gcc -c main_cy.c -o main_cy.o <cflags>
gcc -c main.c -o main_c.o <cflags>
gcc main_c.o main_cy.o -o main.o <ldflags>
当我 运行 Cython 设置 (python setup_cy.py build_ext --inplace
) 时,它在主目录和 [=50= 中成功创建了 *.c、*.h 和 *.so 文件].然后,当我 运行 make 时,它 运行 没有错误并创建了所有 *.o 文件。但是,当我 运行 C 可执行文件 (./main.o
) 时,我得到以下 运行 时间错误:
Traceback (most recent call last):
File "main_cy.pyx", line 1, in init main_cy
# main_cy.pyx
ModuleNotFoundError: No module named 'mod_dir'
Error: could not import module 'main_cy'
谢谢!
好的,我设法找到了解决方案 here(brm 的回答),但我会在此处重新发布,以防其他人有同样的问题。显然 Python shell 会自动将工作目录添加到路径中,但是 Py_Initialize() 在嵌入 C 时不会这样做。要手动执行此操作,我只需要添加main.c 中 Py_Initialize();
之后的第 import sys\nsys.path.insert(0, '')
行。重新编译后,可执行文件按预期运行。
我有一个 Cython 模块,我想在 C 中调用 运行,但我收到 ModuleNotFound 错误。据我所知,我正在按照文档和其他 SO 问题中的说明进行操作,但是除了简单的 1 文件示例(即非模块化)之外,使用 Cython 将 Python 转换为 C 的示例有限。
我在 Ubuntu 上 运行ning Python 3.6(通过 Windows 10 WSL1)。
这是一个显示问题的简化示例:
树:
├── Makefile
├── main.c
├── main_cy.pyx
├── mod_dir
│ ├── __init__.pxd #empty
│ ├── mod.pxd
│ └── mod.pyx
└── setup_cy.py
mod_dir/mod.pxd:
cdef public int say_hello_from_mod() except -1
mod_dir/mod.pyx:
TEXT_TO_SAY = 'Hello from Python!'
cdef public int say_hello_from_mod() except -1:
print(TEXT_TO_SAY)
return 0
main_cy.pyx:
print('hello from main_cy')
from mod_dir.mod cimport say_hello_from_mod
cdef public int say_hello_from_main_cy() except -1:
say_hello_from_mod()
return 0
main.c:
#include "main_cy.h"
int main(int argc, char *argv[])
{
PyObject *pmodule;
wchar_t *program;
program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0], got %d arguments\n", argc);
exit(1);
}
/* Add a built-in module, before Py_Initialize */
if (PyImport_AppendInittab("main_cy", PyInit_main_cy) == -1) {
fprintf(stderr, "Error: could not extend in-built modules table\n");
exit(1);
}
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(program);
/* Initialize the Python interpreter. Required. If this step fails, it will be a fatal error. */
Py_Initialize();
/* Optionally import the module; alternatively, import can be deferred until the main_cy script imports it. */
pmodule = PyImport_ImportModule("main_cy");
if (!pmodule) {
PyErr_Print();
fprintf(stderr, "Error: could not import module 'main_cy'\n");
goto exit_with_error;
}
printf("Hello from C!\n");
/* Now call into your module code. */
if (say_hello_from_main_cy() < 0) {
PyErr_Print();
fprintf(stderr, "Error in Python code, exception was printed.\n");
goto exit_with_error;
}
/* Clean up after using CPython. */
PyMem_RawFree(program);
Py_Finalize();
return 0;
/* Clean up in the error cases above. */
exit_with_error:
PyMem_RawFree(program);
Py_Finalize();
return 1;
}
setup_cy.py:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize(['mod_dir/mod.pyx', 'main_cy.pyx'], annotate=False,language_level=3, include_path=['./', './mod_dir/'])
)
生成文件:
all:
gcc -c main_cy.c -o main_cy.o <cflags>
gcc -c main.c -o main_c.o <cflags>
gcc main_c.o main_cy.o -o main.o <ldflags>
当我 运行 Cython 设置 (python setup_cy.py build_ext --inplace
) 时,它在主目录和 [=50= 中成功创建了 *.c、*.h 和 *.so 文件].然后,当我 运行 make 时,它 运行 没有错误并创建了所有 *.o 文件。但是,当我 运行 C 可执行文件 (./main.o
) 时,我得到以下 运行 时间错误:
Traceback (most recent call last):
File "main_cy.pyx", line 1, in init main_cy
# main_cy.pyx
ModuleNotFoundError: No module named 'mod_dir'
Error: could not import module 'main_cy'
谢谢!
好的,我设法找到了解决方案 here(brm 的回答),但我会在此处重新发布,以防其他人有同样的问题。显然 Python shell 会自动将工作目录添加到路径中,但是 Py_Initialize() 在嵌入 C 时不会这样做。要手动执行此操作,我只需要添加main.c 中 Py_Initialize();
之后的第 import sys\nsys.path.insert(0, '')
行。重新编译后,可执行文件按预期运行。