带有数据文件的Python C扩展

时间:2012-06-13 22:12:55

标签: python c distutils

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

我可以硬编码C扩展中已安装数据文件的路径(可行),但这显然无法在具有不同安装目录的系统上运行。我需要在Linux和Windows下安装此扩展程序。

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

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

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

1 个答案:

答案 0 :(得分:0)

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

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

无论如何,如果有人能告诉我如何更好地做到这一点,我仍然会感到高兴,所以我会把它打开,但我想我会给出答案,以帮助任何有同样问题的人没有更好的答案即将到来,因为我认为这可能会澄清问题。