/* Module definition and import implementation */ #include "Python.h" #include "Python-ast.h"#include "pyarena.h"#include "pythonrun.h"#include "errcode.h"#include "marshal.h"#include "code.h"#include "compile.h"#include "eval.h"#include "osdefs.h"#include "importdl.h" #ifdef HAVE_FCNTL_H#include <fcntl.h>#endif#ifdef __cplusplusextern "C" { #endif extern time_t PyOS_GetLastModificationTime(char *, FILE *); /* In getmtime.c */ /* Magic word to reject .pyc files generated by other Python versions. It should change for each incompatible change to the bytecode. The value of CR and LF is incorporated so if you ever read or write a .pyc file in text mode the magic number will be wrong; also, the Apple MPW compiler swaps their values, botching string constants. The magic numbers must be spaced apart atleast 2 values, as the -U interpeter flag will cause MAGIC+1 being used. They have been odd numbers for some time now. There were a variety of old schemes for setting the magic number. The current working scheme is to increment the previous value by 10. Known values: Python 1.5: 20121 Python 1.5.1: 20121 Python 1.5.2: 20121 Python 1.6: 50428 Python 2.0: 50823 Python 2.0.1: 50823 Python 2.1: 60202 Python 2.1.1: 60202 Python 2.1.2: 60202 Python 2.2: 60717 Python 2.3a0: 62011 Python 2.3a0: 62021 Python 2.3a0: 62011 (!) Python 2.4a0: 62041 Python 2.4a3: 62051 Python 2.4b1: 62061 Python 2.5a0: 62071 Python 2.5a0: 62081 (ast-branch) Python 2.5a0: 62091 (with) Python 2.5a0: 62092 (changed WITH_CLEANUP opcode) Python 2.5b3: 62101 (fix wrong code: for x, in ...) Python 2.5b3: 62111 (fix wrong code: x += yield) Python 2.5c1: 62121 (fix wrong lnotab with for loops and storing constants that should have been removed) Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp).*/#define MAGIC (62131 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the compiler works which are enabled by command line switches. */static long pyc_magic = MAGIC; /* See _PyImport_FixupExtension() below */static PyObject *extensions = NULL; /* This table is defined in config.c: */extern struct _inittab _PyImport_Inittab[]; struct _inittab *PyImport_Inittab = _PyImport_Inittab; /* these tables define the module suffixes that Python recognizes */struct filedescr * _PyImport_Filetab = NULL; #ifdef RISCOSstatic const struct filedescr _PyImport_StandardFiletab[] = { {"/py", "U", PY_SOURCE}, {0, 0}};#elsestatic const struct filedescr _PyImport_StandardFiletab[] = { {".py", "U", PY_SOURCE}, {0, 0}};#endif static PyTypeObject NullImporterType; /* Forward reference */ /* Initialize things */ void_PyImport_Init(void){ const struct filedescr *scan; struct filedescr *filetab; int countD = 0; int countS = 0; /* prepare _PyImport_Filetab: copy entries from _PyImport_DynLoadFiletab and _PyImport_StandardFiletab. */ for (scan = _PyImport_DynLoadFiletab; scan->suffix != NULL; ++scan) ++countD; for (scan = _PyImport_StandardFiletab; scan->suffix != NULL; ++scan) ++countS; filetab = PyMem_NEW(struct filedescr, countD + countS + 1); if (filetab == NULL) Py_FatalError("Can't initialize import file table."); memcpy(filetab, _PyImport_DynLoadFiletab, countD * sizeof(struct filedescr)); memcpy(filetab + countD, _PyImport_StandardFiletab, countS * sizeof(struct filedescr)); filetab[countD + countS].suffix = NULL; _PyImport_Filetab = filetab; if (Py_OptimizeFlag) { /* Replace ".pyc" with ".pyo" in _PyImport_Filetab */ for (; filetab->suffix != NULL; filetab++) {#ifndef RISCOS if (strcmp(filetab->suffix, ".pyc") == 0) filetab->suffix = ".pyo";#else if (strcmp(filetab->suffix, "/pyc") == 0) filetab->suffix = "/pyo";#endif } } if (Py_UnicodeFlag) { /* Fix the pyc_magic so that byte compiled code created using the all-Unicode method doesn't interfere with code created in normal operation mode. */ pyc_magic = MAGIC + 1; }} void_PyImportHooks_Init(void){ PyObject *v, *path_hooks = NULL, *zimpimport; int err = 0; /* adding sys.path_hooks and sys.path_importer_cache, setting up zipimport */ if (PyType_Ready(&NullImporterType) < 0) goto error; if (Py_VerboseFlag) PySys_WriteStderr("# installing zipimport hook\n"); v = PyList_New(0); if (v == NULL) goto error; err = PySys_SetObject("meta_path", v); Py_DECREF(v); if (err) goto error; v = PyDict_New(); if (v == NULL) goto error; err = PySys_SetObject("path_importer_cache", v); Py_DECREF(v); if (err) goto error; path_hooks = PyList_New(0); if (path_hooks == NULL) goto error; err = PySys_SetObject("path_hooks", path_hooks); if (err) { error: PyErr_Print(); Py_FatalError("initializing sys.meta_path, sys.path_hooks, " "path_importer_cache, or NullImporter failed" ); } zimpimport = PyImport_ImportModule("zipimport"); if (zimpimport == NULL) { PyErr_Clear(); /* No zip import module -- okay */ if (Py_VerboseFlag) PySys_WriteStderr("# can't import zipimport\n"); } else { PyObject *zipimporter = PyObject_GetAttrString(zimpimport, "zipimporter"); Py_DECREF(zimpimport); if (zipimporter == NULL) { PyErr_Clear(); /* No zipimporter object -- okay */ if (Py_VerboseFlag) PySys_WriteStderr( "# can't import zipimport.zipimporter\n"); } else { /* sys.path_hooks.append(zipimporter) */ err = PyList_Append(path_hooks, zipimporter); Py_DECREF(zipimporter); if (err) goto error; if (Py_VerboseFlag) PySys_WriteStderr( "# installed zipimport hook\n"); } } Py_DECREF(path_hooks);} void_PyImport_Fini(void){ Py_XDECREF(extensions); extensions = NULL; PyMem_DEL(_PyImport_Filetab); _PyImport_Filetab = NULL;} /* Locking primitives to prevent parallel imports of the same module in different threads to return with a partially loaded module. These calls are serialized by the global interpreter lock. */ #ifdef WITH_THREAD #include "pythread.h" static PyThread_type_lock import_lock = 0;static long import_lock_thread = -1;static int import_lock_level = 0; static voidlock_import(void){ long me = PyThread_get_thread_ident(); if (me == -1) return; /* Too bad */ if (import_lock == NULL) { import_lock = PyThread_allocate_lock(); if (import_lock == NULL) return; /* Nothing much we can do. */ } if (import_lock_thread == me) { import_lock_level++; return; } if (import_lock_thread != -1 || !PyThread_acquire_lock(import_lock, 0)) { PyThreadState *tstate = PyEval_SaveThread(); PyThread_acquire_lock(import_lock, 1); PyEval_RestoreThread(tstate); } import_lock_thread = me; import_lock_level = 1;} static intunlock_import(void){ long me = PyThread_get_thread_ident(); if (me == -1 || import_lock == NULL) return 0; /* Too bad */ if (import_lock_thread != me) return -1; import_lock_level--; if (import_lock_level == 0) { import_lock_thread = -1; PyThread_release_lock(import_lock); } return 1;} /* This function is called from PyOS_AfterFork to ensure that newly created child processes do not share locks with the parent. */ void_PyImport_ReInitLock(void){#ifdef _AIX if (import_lock != NULL) import_lock = PyThread_allocate_lock();#endif} #else #define lock_import()#define unlock_import() 0 #endif static PyObject *imp_lock_held(PyObject *self, PyObject *noargs){#ifdef WITH_THREAD return PyBool_FromLong(import_lock_thread != -1);#else return PyBool_FromLong(0);#endif} static PyObject *imp_acquire_lock(PyObject *self, PyObject *noargs){#ifdef WITH_THREAD lock_import();#endif Py_INCREF(Py_None); return Py_None;} static PyObject *imp_release_lock(PyObject *self, PyObject *noargs){#ifdef WITH_THREAD if (unlock_import() < 0) { PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); return NULL; }#endif Py_INCREF(Py_None); return Py_None;} static voidimp_modules_reloading_clear (void){ PyInterpreterState *interp = PyThreadState_Get()->interp; if (interp->modules_reloading == NULL) return; PyDict_Clear(interp->modules_reloading); return;} /* Helper for sys */ PyObject *PyImport_GetModuleDict(void){ PyInterpreterState *interp = PyThreadState_GET()->interp; if (interp->modules == NULL) Py_FatalError("PyImport_GetModuleDict: no module dictionary!"); return interp->modules;} /* List of names to clear in sys */static char* sys_deletes[] = { "path", "argv", "ps1", "ps2", "exitfunc", "exc_type", "exc_value", "exc_traceback", "last_type", "last_value", "last_traceback", "path_hooks", "path_importer_cache", "meta_path", NULL}; static char* sys_files[] = { "stdin", "__stdin__", "stdout", "__stdout__", "stderr", "__stderr__", NULL}; /* Un-initialize things, as good as we can */ voidPyImport_Cleanup(void){ Py_ssize_t pos, ndone; char *name; PyObject *key, *value, *dict; PyInterpreterState *interp = PyThreadState_GET()->interp; PyObject *modules = interp->modules; if (modules == NULL) return; /* Already done */ /* Delete some special variables first. These are common places where user values hide and people complain when their destructors fail. Since the modules containing them are deleted *last* of all, they would come too late in the normal destruction order. Sigh. */ value = PyDict_GetItemString(modules, "__builtin__"); if (value != NULL && PyModule_Check(value)) { dict = PyModule_GetDict(value); if (Py_VerboseFlag) PySys_WriteStderr("# clear __builtin__._\n"); PyDict_SetItemString(dict, "_", Py_None); } value = PyDict_GetItemString(modules, "sys"); if (value != NULL && PyModule_Check(value)) { char **p; PyObject *v; dict = PyModule_GetDict(value); for (p = sys_deletes; *p != NULL; p++) { if (Py_VerboseFlag) PySys_WriteStderr("# clear sys.%s\n", *p); PyDict_SetItemString(dict, *p, Py_None); } for (p = sys_files; *p != NULL; p+=2) { if (Py_VerboseFlag) PySys_WriteStderr("# restore sys.%s\n", *p); v = PyDict_GetItemString(dict, *(p+1)); if (v == NULL) v = Py_None; PyDict_SetItemString(dict, *p, v); } } /* First, delete __main__ */ value = PyDict_GetItemString(modules, "__main__"); if (value != NULL && PyModule_Check(value)) { if (Py_VerboseFlag) PySys_WriteStderr("# cleanup __main__\n"); _PyModule_Clear(value); PyDict_SetItemString(modules, "__main__", Py_None); } /* The special treatment of __builtin__ here is because even when it's not referenced as a module, its dictionary is referenced by almost every module's __builtins__. Since deleting a module clears its dictionary (even if there are references left to it), we need to delete the __builtin__ module last. Likewise, we don't delete sys until the very end because it is implicitly referenced (e.g. by print). Also note that we 'delete' modules by replacing their entry in the modules dict with None, rather than really deleting them; this avoids a rehash of the modules dictionary and also marks them as "non existent" so they won't be re-imported. */ /* Next, repeatedly delete modules with a reference count of one (skipping __builtin__ and sys) and delete them */ do { ndone = 0; pos = 0; while (PyDict_Next(modules, &pos, &key, &value)) { if (value->ob_refcnt != 1) continue; if (PyString_Check(key) && PyModule_Check(value)) { name = PyString_AS_STRING(key); if (strcmp(name, "__builtin__") == 0) continue; if (strcmp(name, "sys") == 0) continue; if (Py_VerboseFlag) PySys_WriteStderr( "# cleanup[1] %s\n", name); _PyModule_Clear(value); PyDict_SetItem(modules, key, Py_None); ndone++; } } } while (ndone > 0); /* Next, delete all modules (still skipping __builtin__ and sys) */ pos = 0; while (PyDict_Next(modules, &pos, &key, &value)) { if (PyString_Check(key) && PyModule_Check(value)) { name = PyString_AS_STRING(key); if (strcmp(name, "__builtin__") == 0) continue; if (strcmp(name, "sys") == 0) continue; if (Py_VerboseFlag) PySys_WriteStderr("# cleanup[2] %s\n", name); _PyModule_Clear(value); PyDict_SetItem(modules, key, Py_None); } } /* Next, delete sys and __builtin__ (in that order) */ value = PyDict_GetItemString(modules, "sys"); if (value != NULL && PyModule_Check(value)) { if (Py_VerboseFlag) PySys_WriteStderr("# cleanup sys\n"); _PyModule_Clear(value); PyDict_SetItemString(modules, "sys", Py_None); } value = PyDict_GetItemString(modules, "__builtin__"); if (value != NULL && PyModule_Check(value)) { if (Py_VerboseFlag) PySys_WriteStderr("# cleanup __builtin__\n"); _PyModule_Clear(value); PyDict_SetItemString(modules, "__builtin__", Py_None); }Lines 1–500 of 3033. Load more
/* Module definition and import implementation */ #include "Python.h" #include "Python-ast.h" #include "pyarena.h" #include "pythonrun.h" #include "errcode.h" #include "marshal.h" #include "code.h" #include "compile.h" #include "eval.h" #include "osdefs.h" #include "importdl.h" #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif #ifdef __cplusplus extern "C" { #endif extern time_t PyOS_GetLastModificationTime(char *, FILE *); /* In getmtime.c */ /* Magic word to reject .pyc files generated by other Python versions. It should change for each incompatible change to the bytecode. The value of CR and LF is incorporated so if you ever read or write a .pyc file in text mode the magic number will be wrong; also, the Apple MPW compiler swaps their values, botching string constants. The magic numbers must be spaced apart atleast 2 values, as the -U interpeter flag will cause MAGIC+1 being used. They have been odd numbers for some time now. There were a variety of old schemes for setting the magic number. The current working scheme is to increment the previous value by 10. Known values: Python 1.5: 20121 Python 1.5.1: 20121 Python 1.5.2: 20121 Python 1.6: 50428 Python 2.0: 50823 Python 2.0.1: 50823 Python 2.1: 60202 Python 2.1.1: 60202 Python 2.1.2: 60202 Python 2.2: 60717 Python 2.3a0: 62011 Python 2.3a0: 62021 Python 2.3a0: 62011 (!) Python 2.4a0: 62041 Python 2.4a3: 62051 Python 2.4b1: 62061 Python 2.5a0: 62071 Python 2.5a0: 62081 (ast-branch) Python 2.5a0: 62091 (with) Python 2.5a0: 62092 (changed WITH_CLEANUP opcode) Python 2.5b3: 62101 (fix wrong code: for x, in ...) Python 2.5b3: 62111 (fix wrong code: x += yield) Python 2.5c1: 62121 (fix wrong lnotab with for loops and storing constants that should have been removed) Python 2.5c2: 62131 (fix wrong code: for x, in ... in listcomp/genexp) . */ #define MAGIC (62131 | ((long)'\r'<<16) | ((long)'\n'<<24)) /* Magic word as global; note that _PyImport_Init() can change the value of this global to accommodate for alterations of how the compiler works which are enabled by command line switches. */ static long pyc_magic = MAGIC; /* See _PyImport_FixupExtension() below */ static PyObject *extensions = NULL; /* This table is defined in config.c: */ extern struct _inittab _PyImport_Inittab[]; struct _inittab *PyImport_Inittab = _PyImport_Inittab; /* these tables define the module suffixes that Python recognizes */ struct filedescr * _PyImport_Filetab = NULL; #ifdef RISCOS static const struct filedescr _PyImport_StandardFiletab[] = { {"/py", "U", PY_SOURCE}, {0, 0} }; #else static const struct filedescr _PyImport_StandardFiletab[] = { {".py", "U", PY_SOURCE}, {0, 0} }; #endif static PyTypeObject NullImporterType; /* Forward reference */ /* Initialize things */ void _PyImport_Init(void) { const struct filedescr *scan; struct filedescr *filetab; int countD = 0; int countS = 0; /* prepare _PyImport_Filetab: copy entries from _PyImport_DynLoadFiletab and _PyImport_StandardFiletab. */ for (scan = _PyImport_DynLoadFiletab; scan->suffix != NULL; ++scan) ++countD; for (scan = _PyImport_StandardFiletab; scan->suffix != NULL; ++scan) ++countS; filetab = PyMem_NEW(struct filedescr, countD + countS + 1); if (filetab == NULL) Py_FatalError("Can't initialize import file table."); memcpy(filetab, _PyImport_DynLoadFiletab, countD * sizeof(struct filedescr)); memcpy(filetab + countD, _PyImport_StandardFiletab, countS * sizeof(struct filedescr)); filetab[countD + countS].suffix = NULL; _PyImport_Filetab = filetab; if (Py_OptimizeFlag) { /* Replace ".pyc" with ".pyo" in _PyImport_Filetab */ for (; filetab->suffix != NULL; filetab++) { #ifndef RISCOS if (strcmp(filetab->suffix, ".pyc") == 0) filetab->suffix = ".pyo"; #else if (strcmp(filetab->suffix, "/pyc") == 0) filetab->suffix = "/pyo"; #endif } } if (Py_UnicodeFlag) { /* Fix the pyc_magic so that byte compiled code created using the all-Unicode method doesn't interfere with code created in normal operation mode. */ pyc_magic = MAGIC + 1; } } void _PyImportHooks_Init(void) { PyObject *v, *path_hooks = NULL, *zimpimport; int err = 0; /* adding sys.path_hooks and sys.path_importer_cache, setting up zipimport */ if (PyType_Ready(&NullImporterType) < 0) goto error; if (Py_VerboseFlag) PySys_WriteStderr("# installing zipimport hook\n"); v = PyList_New(0); if (v == NULL) goto error; err = PySys_SetObject("meta_path", v); Py_DECREF(v); if (err) goto error; v = PyDict_New(); if (v == NULL) goto error; err = PySys_SetObject("path_importer_cache", v); Py_DECREF(v); if (err) goto error; path_hooks = PyList_New(0); if (path_hooks == NULL) goto error; err = PySys_SetObject("path_hooks", path_hooks); if (err) { error: PyErr_Print(); Py_FatalError("initializing sys.meta_path, sys.path_hooks, " "path_importer_cache, or NullImporter failed" ); } zimpimport = PyImport_ImportModule("zipimport"); if (zimpimport == NULL) { PyErr_Clear(); /* No zip import module -- okay */ if (Py_VerboseFlag) PySys_WriteStderr("# can't import zipimport\n"); } else { PyObject *zipimporter = PyObject_GetAttrString(zimpimport, "zipimporter"); Py_DECREF(zimpimport); if (zipimporter == NULL) { PyErr_Clear(); /* No zipimporter object -- okay */ if (Py_VerboseFlag) PySys_WriteStderr( "# can't import zipimport.zipimporter\n"); } else { /* sys.path_hooks.append(zipimporter) */ err = PyList_Append(path_hooks, zipimporter); Py_DECREF(zipimporter); if (err) goto error; if (Py_VerboseFlag) PySys_WriteStderr( "# installed zipimport hook\n"); } } Py_DECREF(path_hooks); } void _PyImport_Fini(void) { Py_XDECREF(extensions); extensions = NULL; PyMem_DEL(_PyImport_Filetab); _PyImport_Filetab = NULL; } /* Locking primitives to prevent parallel imports of the same module in different threads to return with a partially loaded module. These calls are serialized by the global interpreter lock. */ #ifdef WITH_THREAD #include "pythread.h" static PyThread_type_lock import_lock = 0; static long import_lock_thread = -1; static int import_lock_level = 0; static void lock_import(void) { long me = PyThread_get_thread_ident(); if (me == -1) return; /* Too bad */ if (import_lock == NULL) { import_lock = PyThread_allocate_lock(); if (import_lock == NULL) return; /* Nothing much we can do. */ } if (import_lock_thread == me) { import_lock_level++; return; } if (import_lock_thread != -1 || !PyThread_acquire_lock(import_lock, 0)) { PyThreadState *tstate = PyEval_SaveThread(); PyThread_acquire_lock(import_lock, 1); PyEval_RestoreThread(tstate); } import_lock_thread = me; import_lock_level = 1; } static int unlock_import(void) { long me = PyThread_get_thread_ident(); if (me == -1 || import_lock == NULL) return 0; /* Too bad */ if (import_lock_thread != me) return -1; import_lock_level--; if (import_lock_level == 0) { import_lock_thread = -1; PyThread_release_lock(import_lock); } return 1; } /* This function is called from PyOS_AfterFork to ensure that newly created child processes do not share locks with the parent. */ void _PyImport_ReInitLock(void) { #ifdef _AIX if (import_lock != NULL) import_lock = PyThread_allocate_lock(); #endif } #else #define lock_import() #define unlock_import() 0 #endif static PyObject * imp_lock_held(PyObject *self, PyObject *noargs) { #ifdef WITH_THREAD return PyBool_FromLong(import_lock_thread != -1); #else return PyBool_FromLong(0); #endif } static PyObject * imp_acquire_lock(PyObject *self, PyObject *noargs) { #ifdef WITH_THREAD lock_import(); #endif Py_INCREF(Py_None); return Py_None; } static PyObject * imp_release_lock(PyObject *self, PyObject *noargs) { #ifdef WITH_THREAD if (unlock_import() < 0) { PyErr_SetString(PyExc_RuntimeError, "not holding the import lock"); return NULL; } #endif Py_INCREF(Py_None); return Py_None; } static void imp_modules_reloading_clear (void) { PyInterpreterState *interp = PyThreadState_Get()->interp; if (interp->modules_reloading == NULL) return; PyDict_Clear(interp->modules_reloading); return; } /* Helper for sys */ PyObject * PyImport_GetModuleDict(void) { PyInterpreterState *interp = PyThreadState_GET()->interp; if (interp->modules == NULL) Py_FatalError("PyImport_GetModuleDict: no module dictionary!"); return interp->modules; } /* List of names to clear in sys */ static char* sys_deletes[] = { "path", "argv", "ps1", "ps2", "exitfunc", "exc_type", "exc_value", "exc_traceback", "last_type", "last_value", "last_traceback", "path_hooks", "path_importer_cache", "meta_path", NULL }; static char* sys_files[] = { "stdin", "__stdin__", "stdout", "__stdout__", "stderr", "__stderr__", NULL }; /* Un-initialize things, as good as we can */ void PyImport_Cleanup(void) { Py_ssize_t pos, ndone; char *name; PyObject *key, *value, *dict; PyInterpreterState *interp = PyThreadState_GET()->interp; PyObject *modules = interp->modules; if (modules == NULL) return; /* Already done */ /* Delete some special variables first. These are common places where user values hide and people complain when their destructors fail. Since the modules containing them are deleted *last* of all, they would come too late in the normal destruction order. Sigh. */ value = PyDict_GetItemString(modules, "__builtin__"); if (value != NULL && PyModule_Check(value)) { dict = PyModule_GetDict(value); if (Py_VerboseFlag) PySys_WriteStderr("# clear __builtin__._\n"); PyDict_SetItemString(dict, "_", Py_None); } value = PyDict_GetItemString(modules, "sys"); if (value != NULL && PyModule_Check(value)) { char **p; PyObject *v; dict = PyModule_GetDict(value); for (p = sys_deletes; *p != NULL; p++) { if (Py_VerboseFlag) PySys_WriteStderr("# clear sys.%s\n", *p); PyDict_SetItemString(dict, *p, Py_None); } for (p = sys_files; *p != NULL; p+=2) { if (Py_VerboseFlag) PySys_WriteStderr("# restore sys.%s\n", *p); v = PyDict_GetItemString(dict, *(p+1)); if (v == NULL) v = Py_None; PyDict_SetItemString(dict, *p, v); } } /* First, delete __main__ */ value = PyDict_GetItemString(modules, "__main__"); if (value != NULL && PyModule_Check(value)) { if (Py_VerboseFlag) PySys_WriteStderr("# cleanup __main__\n"); _PyModule_Clear(value); PyDict_SetItemString(modules, "__main__", Py_None); } /* The special treatment of __builtin__ here is because even when it's not referenced as a module, its dictionary is referenced by almost every module's __builtins__. Since deleting a module clears its dictionary (even if there are references left to it), we need to delete the __builtin__ module last. Likewise, we don't delete sys until the very end because it is implicitly referenced (e.g. by print). Also note that we 'delete' modules by replacing their entry in the modules dict with None, rather than really deleting them; this avoids a rehash of the modules dictionary and also marks them as "non existent" so they won't be re-imported. */ /* Next, repeatedly delete modules with a reference count of one (skipping __builtin__ and sys) and delete them */ do { ndone = 0; pos = 0; while (PyDict_Next(modules, &pos, &key, &value)) { if (value->ob_refcnt != 1) continue; if (PyString_Check(key) && PyModule_Check(value)) { name = PyString_AS_STRING(key); if (strcmp(name, "__builtin__") == 0) continue; if (strcmp(name, "sys") == 0) continue; if (Py_VerboseFlag) PySys_WriteStderr( "# cleanup[1] %s\n", name); _PyModule_Clear(value); PyDict_SetItem(modules, key, Py_None); ndone++; } } } while (ndone > 0); /* Next, delete all modules (still skipping __builtin__ and sys) */ pos = 0; while (PyDict_Next(modules, &pos, &key, &value)) { if (PyString_Check(key) && PyModule_Check(value)) { name = PyString_AS_STRING(key); if (strcmp(name, "__builtin__") == 0) continue; if (strcmp(name, "sys") == 0) continue; if (Py_VerboseFlag) PySys_WriteStderr("# cleanup[2] %s\n", name); _PyModule_Clear(value); PyDict_SetItem(modules, key, Py_None); } } /* Next, delete sys and __builtin__ (in that order) */ value = PyDict_GetItemString(modules, "sys"); if (value != NULL && PyModule_Check(value)) { if (Py_VerboseFlag) PySys_WriteStderr("# cleanup sys\n"); _PyModule_Clear(value); PyDict_SetItemString(modules, "sys", Py_None); } value = PyDict_GetItemString(modules, "__builtin__"); if (value != NULL && PyModule_Check(value)) { if (Py_VerboseFlag) PySys_WriteStderr("# cleanup __builtin__\n"); _PyModule_Clear(value); PyDict_SetItemString(modules, "__builtin__", Py_None); }