【发布时间】:2020-09-18 14:14:33
【问题描述】:
我有一个 cython 源文件,我想在其中导入本地 python 模块。 这个 cython 源文件使用 cython(python3 语法)翻译成 c++ 源,然后编译成库,然后在 C++ 主程序中使用。
在执行主程序时,本地 python 模块的导入失败,因为执行的代码不知道其模块的位置。我尝试在我的 pyx 文件中使用 python3 的本地导入功能,但无济于事。
我想出的唯一可行的解决方案(也是最明显的一个)是使用sys.path.append 更新python 的模块搜索路径。问题是我必须对这条路径进行硬编码,这很难看。
如果可以在源文件的 cython 代码位置中检索(我可以从中导出绝对路径),我试图找到任何提示,但没有成功。通常的 Pythonic 方法会失败 - 例如,原因之一是 __file__ 的计算结果为 built-in,并且在运行时检索绝对路径会给出运行可执行文件的路径。
旁注:我所做的搜索之一是在 GitHub 搜索引擎中查询 cython 文件中出现的 sys.path.append。有趣的是,所有结果要么具有硬编码的路径,要么与文件系统中 cython 源文件的位置无关。
所以我的问题是,是否可以在 cython 代码中可靠地检索其源文件的位置?
免责声明:我可以想象在构建从 cython 派生的 C++ 文件时检测构建系统以将预处理器变量集传递给相关路径,然后在代码中访问它,但这看起来有点矫枉过正。
示例:
bulba.py
def fn():
print('blah')
bulbulator.pyx
# tag: cpp
# tag: py3only
import sys
sys.path.append('/absolute_path_to_folder_with_bulba_py') # <-- this is the key part. I'd like to replace the hardcoded path with something better
from bulba import fn
fn()
bulbulator.pyx 被翻译成 cpp:
cython -3 --cplus bulbulator.pyx
lib_wrapper.cpp (这个库和链接到它的可执行文件的位置与 py/pyx 源代码及其翻译的 c++ 部分的位置不同)
// import headers generated by cython
#include "bulbulator_api.h"
#include "bulbulator.h"
// global initialization of the cythonized part
__attribute__((constructor))
static void
__library_init()
{
if (int err = PyImport_AppendInittab("bulbulator", PyInit_bulbulator); err != 0)
{
std::fprintf(stderr, "PyImport_AppendInittab(bulbulator) failed with status code=%d\n", err);
std::exit(1);
}
Py_Initialize();
if (import_bulbulator() == -1) // <-- here it fails if I comment out sys.path.append, because bulbulator needs to know the location of bulba.py
{
PyErr_Print();
}
}
【问题讨论】:
-
@ead
pyx文件被翻译成cpp,然后被编译成一个静态库,一个可执行文件与之链接。我有另一个应用程序,它遵循完全相同的方案,只是它没有在 cythonized 代码中导入本地 python 模块并且它可以工作。 -
@ead 我不确定您提供的链接中的解决方案是否可以在这里工作。看起来它适用于导入模块也是 pyx 模块的情况,而在我的情况下它是 vanilla python,所以没有定义函数可以传递给
PyImport_AppendInittab。
标签: cython