如何访问 Python C 扩展中的当前文件路径

How to Access Current File Path in Python C Extension

在Python中可以通过__file__属性获取当前文件路径

print(__file__)

如何从 Python C 扩展访问此属性?我试了下面的代码,但是属性不存在。

if (PyObject_HasAttrString(module, "__file__")) {
    PyObject *string = PyObject_GetAttrString(module, "__file__");
    const char *path = PyUnicode_AsUTF8(string);
}

这取决于您想要访问 __file__ 属性的时间以及您创建模块的具体方式。

在单阶段初始化中(当您在 PyInit_yourmodulename 中调用 PyModule_Create 时)__file__ 设置为 之后 PyInit_*函数被调用。因此,您只能在那之后访问它,当模块完全导入时。

multi-phase initialization, where PyInit_yourmodulename returns a PyModuleDef object and then the Py_mod_create slot of that PyModuleDef is called, you can set the filename from the spec passed to Py_mod_create. The ModuleSpec 中对象有一个属性 origin。这对应于从中加载模块的文件。因此,您可以从 spec.origin.

设置模块的 __file__ 属性

如果您在 PyInit_yourmodulename 系统之外创建模块(例如,从单个文件创建多个模块)那么您就不走运了,您将不得不弄清楚 __file__是你自己。

感谢@DavidW,我现在可以访问 __file__ 属性。

static int module_exec(PyObject *self) {
    PyObject *string = PyObject_GetAttrString(self, "__file__");
    const char *path = PyUnicode_AsUTF8(string);

    printf("Current path: %s\n", path);
    return 0;
}

static PyModuleDef_Slot ModuleSlots[] = {
    {Py_mod_exec, module_exec},
    {0, NULL}
};

static struct PyModuleDef Module = {
    .m_base = PyModuleDef_HEAD_INIT,
    .m_name = "__init__",
    .m_size = 0,
    .m_slots = ModuleSlots
};

PyMODINIT_FUNC PyInit_Module(void) {
    printf("Initialising...");
    return PyModuleDef_Init(&Module);
}

我本可以添加 Py_mod_create 插槽,但我的项目不需要它。