This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Not possible to clear PyImport_Inittab after PyImport_AppendInittab
Type: behavior Stage:
Components: C API Versions: Python 3.11
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: daniel-falk, vstinner
Priority: normal Keywords:

Created on 2021-12-03 14:11 by daniel-falk, last changed 2022-04-11 14:59 by admin.

Messages (3)
msg407590 - (view) Author: Daniel (daniel-falk) Date: 2021-12-03 14:11
Hello,

When embedding Python into a C application and not using Py_RunMain it is not possible to remove a module added to PyImport_Inittab even if the interpreter is finalized and a new is created.

One reason for not using Py_RunMain is to use python as a subprocessor to my primary C application by initializing an interpreter, run some python code, then go back to execute some C code and again execute some python code in the same interpreter. After a while I might want to finalize the interpreter and create a new one without the module added to inittab, still being in the same process.

See example:

#include <Python.h>


/*
 * Create a python interpreter, run a command and delete the interpreter
 */
void run_in_new_interpreter(char *cmd) {
    Py_Initialize();

    PyRun_SimpleString(cmd);

    if (Py_FinalizeEx() < 0) {
        exit(120);
    }
}

/*
 * Create a module "my_spam" but do not append it to inittab
 */
static PyModuleDef EmbModule = {
      PyModuleDef_HEAD_INIT, "my_spam", NULL, -1,
      NULL,
      NULL, NULL, NULL, NULL
};

static PyObject* PyInit_emb(void) {
    return PyModule_Create(&EmbModule);
}

/*
 * Main program
 */
char *LIST_MODULES_CMD="try:\n import my_spam; print('SPAM!');\nexcept:\n print('no mod my_spam')";

int main(int argc, char *argv[]) {
    // Run with no "my_spam" module
    run_in_new_interpreter(LIST_MODULES_CMD);

    // Run with "my_spam" module
    PyImport_AppendInittab("my_spam", &PyInit_emb);
    run_in_new_interpreter(LIST_MODULES_CMD);

    // How to run without my_spam? The module is still in the PyImport_Inittab
    // despite the Py_FinalizeEx() call. This list is not reset until
    // _PyImport_Fini2() is called, but that is never exposed in anyi public header,
    // only in Include/internal/pycore_pylifecycle.h
    run_in_new_interpreter(LIST_MODULES_CMD);
    return 0;
}



The output of the program is:

>>> gcc test_embed.c `pkg-config --cflags --libs python-3.6` && ./a.out
no mod my_spam
SPAM!
SPAM!
msg407832 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-12-06 16:26
Currently, the global variable PyImport_Inittab is used. It should be made per-interpreter and I suggest to add something like PyConfig_AppendInittab() to the PyConfig API, so the configuration change would only impact a single interpreter. It would be possible to run two interpreters with two different inittab configuration.
msg407835 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2021-12-06 16:30
See also bpo-44441 (fixed).
History
Date User Action Args
2022-04-11 14:59:53adminsetgithub: 90131
2021-12-06 16:30:09vstinnersetmessages: + msg407835
2021-12-06 16:26:06vstinnersetnosy: + vstinner

messages: + msg407832
versions: + Python 3.11
2021-12-03 14:11:14daniel-falkcreate