我正在尝试编写并安装一个C扩展,用于加载一个120MB的数据文件。使用distutils package_data
参数我已经将数据文件正确安装到与扩展模块相同的文件夹中。但是,C代码不知道如何查找数据文件。
我可以硬编码C扩展中已安装数据文件的路径(可行),但这显然无法在具有不同安装目录的系统上运行。我需要在Linux和Windows下安装此扩展程序。
我尝试使用PyModule_GetFilename()
来获取模块的路径,然后从中构建数据文件的路径,但该函数会引发SystemError: module filename missing
。可能是错误是因为我试图在我的模块init函数中调用它?
如果有必要,我可以在模块初始化之外手动加载数据文件,但我宁愿在导入时自动加载文件。
编辑:所以,我找到了一个解决方法。我写了一个初始化函数,它可以将文件的路径作为参数。从Python,我可以访问模块的__file__
属性,并从那里找出数据文件的路径。然后,如果我在__init__.py
中运行初始化函数,一切都会正常工作。虽然这有效,但我仍然希望那里有人可以给我一个更优雅的解决方案,因为这对我来说非常倒退!
答案 0 :(得分:0)
所以我自己提出了一个更好的解决方案,并且认为我会发布它,以防它帮助其他任何人。
我的项目包含一个带有C扩展名的包(my_module
)。该安装包含_my_extension.so
,__init__.py
和datafile.dat
。在相关部分中,__init__.py
看起来像:
import os
def datafile_path():
return os.path.join(os.path.dirname(__file__), "datafile.dat")
import _my_extension
我的C扩展初始化函数如下所示:
PyMODINIT_FUNC
init_my_extension(void)
{
PyObject *m, *fileobj, *pModule, *pFunc;
m = Py_InitModule3("_my_extension", _my_extension_methods, "A docstring");
if (m == NULL)
return;
pModule = PyImport_ImportModule("my_module");
pFunc = PyObject_GetAttrString(pModule, "datafile_path");
fileobj = PyObject_CallFunction(pFunc, NULL);
Py_DECREF(pFunc);
LoadDataFile(PyString_AS_STRING(fileobj));
Py_DECREF(fileobj);
Py_DECREF(pModule);
}
我显然需要添加一些错误处理,这似乎有点偏,但至少它在模块初始化时加载数据文件,并且工作正常。显然我可以在C中进行大部分datafile_path
计算,但由于我还需要导入模块,并且因为我想要跨平台兼容性,所以使用os
模块似乎更容易。 / p>
无论如何,如果有人能告诉我如何更好地做到这一点,我仍然会感到高兴,所以我会把它打开,但我想我会给出答案,以帮助任何有同样问题的人没有更好的答案即将到来,因为我认为这可能会澄清问题。