Расширение Python C с файлом данных

Я пытаюсь написать и установить расширение C для Python, которое должно загрузить файл данных размером 120 МБ. Используя аргумент distutils package_data, я правильно установил файл данных в ту же папку, что и модуль расширения. Однако код C не знает, как найти файл данных.

Я могу жестко указать путь к установленному файлу данных в расширении C (это работает), но, очевидно, это не сработает в системах с разными каталогами установки. Мне нужно будет установить это расширение как под Linux, так и под Windows.

Я пытался использовать PyModule_GetFilename(), чтобы получить путь к модулю, а затем создать из него путь к файлу данных, но эта функция вызывает SystemError: module filename missing. Возможно, ошибка связана с тем, что я пытаюсь вызвать ее внутри функции инициализации модуля?

При необходимости я могу загрузить файл данных вручную вне инициализации модуля, хотя я предпочитаю загружать файл автоматически при импорте.

РЕДАКТИРОВАТЬ: Итак, я нашел обходной путь. Я написал функцию инициализации, которая может принимать путь к файлу в качестве аргумента. Из Python я могу получить доступ к атрибуту __file__ модуля и выяснить путь к файлу данных оттуда. Затем все работает, если я запускаю функцию инициализации в __init__.py. Хотя это работает, я все еще надеюсь, что кто-то может дать мне более элегантное решение, потому что это кажется мне довольно обратным!


person Julian    schedule 13.06.2012    source источник


Ответы (1)


Поэтому я придумал несколько лучшее решение самостоятельно и подумал, что опубликую его на случай, если оно поможет кому-то еще.

Мой проект состоит из пакета (my_module) с расширением C. Установка содержит _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);
}

Очевидно, мне нужно добавить некоторую обработку ошибок, и это все еще кажется немного неправильным, но, по крайней мере, оно загружает файл данных во время инициализации модуля и работает. Очевидно, что я мог бы выполнить большую часть вычислений datafile_path на C, но поскольку мне все равно нужно было импортировать модуль, и поскольку мне нужна кросс-платформенная совместимость, мне показалось проще просто использовать модуль os.

В любом случае, я все равно был бы счастлив, если бы кто-нибудь мог сказать мне, как это сделать лучше, поэтому я оставлю это открытым, но я подумал, что напишу оба ответа, чтобы помочь любому с той же проблемой, если нет лучшего ответа. ожидается, и потому что я думал, что это может прояснить проблему.

person Julian    schedule 14.06.2012