En Python, puede obtener la ruta del archivo actual con el atributo __file__ .
print(__file__)¿Cómo puedo acceder a este atributo desde una extensión de Python C? Probé el siguiente código, pero el atributo no existe.
if (PyObject_HasAttrString(module, "__file__")) { PyObject *string = PyObject_GetAttrString(module, "__file__"); const char *path = PyUnicode_AsUTF8(string); }Depende de cuándo desee acceder al atributo __file__ y exactamente cómo cree el módulo.
En la inicialización de una sola fase (cuando llama a PyModule_Create dentro de PyInit_yourmodulename ) __file__ se establece después de llamar a la función PyInit_* . Por lo tanto, solo puede acceder a él después de ese punto, cuando el módulo se haya importado por completo.
En la inicialización multifase, donde PyInit_yourmodulename devuelve un objeto PyModuleDef y luego se llama a la ranura Py_mod_create de ese PyModuleDef , puede establecer el nombre de archivo de la spec pasada a Py_mod_create . El objeto ModuleSpec tiene un origin de atributo. Esto corresponde al archivo desde el que se cargó el módulo. Por lo tanto, puede establecer el atributo __file__ de su módulo desde spec.origin .
Si está creando sus módulos fuera del sistema PyInit_yourmodulename (por ejemplo, creando múltiples módulos a partir de un solo archivo), entonces no tendrá suerte y tendrá que averiguar qué __file__ es usted mismo.
Gracias a @DavidW, ahora puedo acceder al atributo __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); } Podría haber agregado la ranura Py_mod_create , pero no la necesito para mi proyecto.