3

我正在尝试为 Python 编写和安装一个 C 扩展,它必须加载一个 120MB 的数据文件。使用 distutilspackage_data参数我已经将数据文件正确安装到与扩展模块相同的文件夹中。但是,C 代码不知道如何找到数据文件。

我可以在 C 扩展中硬编码已安装数据文件的路径(有效),但这显然不适用于具有不同安装目录的系统。我需要在 Linux 和 Windows 下都安装这个扩展。

我尝试使用PyModule_GetFilename()来获取模块的路径,然后从中构建数据文件的路径,但是该函数会引发SystemError: module filename missing. 可能错误是因为我试图在我的模块初始化函数中调用它?

如有必要,我可以在模块初始化之外手动加载数据文件,但我更愿意在导入时自动加载文件。

编辑:所以,我找到了一种解决方法。我写了一个初始化函数,它可以将文件的路径作为参数。从 Python 中,我可以访问模块的__file__属性并从那里找出数据文件的路径。然后,如果我在__init__.py. 虽然这可行,但我仍然希望有人能给我一个更优雅的解决方案,因为这对我来说感觉很倒退!

4

1 回答 1

0

所以我自己想出了一个更好的解决方案,并认为我会发布它以防它帮助其他人。

我的项目包含一个my_module带有 C 扩展名的包 ( )。安装包含_my_extension.so__init__.pydatafile.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模块似乎更容易。

无论如何,如果有人能告诉我如何更好地做到这一点,我仍然会很高兴,所以我会保持开放状态,但我想我会提出一个答案来帮助任何有同样问题的人,以防万一没有更好的答案即将发布,因为我认为它可能会澄清问题。

于 2012-06-14T15:24:57.467 回答