How to Access Current File Path in Python C Extension

In Python, you can get the current file path with the __file__ attribute.

print(__file__)

How can I access this attribute from a Python C Extension? I tried the following code, but the attribute doesn’t exist.

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

Solution 1:

It depends on when you want to access the __file__ attribute and exactly how you create the module.

In single-phase initialization (when you call PyModule_Create within PyInit_yourmodulename) __file__ is set after the PyInit_* function is called. Therefore you can only access it after that point, when the module is fully imported.

In 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 object has an attribute origin. This corresponds to the file that the module was loaded from. Thus you can set the __file__ attribute of your module from spec.origin.

If you're creating your modules outside of the PyInit_yourmodulename system (for example, creating multiple modules from a single file) then you're out of luck and will have to work out what __file__ is yourself.