Add internal routine _PyModule_Clear(), which does approximately what
clear_carefully() used to do in import.c.  Differences: leave only
__builtins__ alone in the 2nd pass; and don't clear the dictionary (on
the theory that as long as there are references left to the
dictionary, those might be destructors that might expect __builtins__
to be alive when they run; and __builtins__ can't normally be part of
a cycle).
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 1ba1a1b..7a41439 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -93,6 +93,55 @@
 	return PyString_AsString(nameobj);
 }
 
+void
+_PyModule_Clear(m)
+	PyObject *m;
+{
+	/* To make the execution order of destructors for global
+	   objects a bit more predictable, we first zap all objects
+	   whose name starts with a single underscore, before we clear
+	   the entire dictionary.  We zap them by replacing them with
+	   None, rather than deleting them from the dictionary, to
+	   avoid rehashing the dictionary (to some extent). */
+
+	int pos;
+	PyObject *key, *value;
+	PyObject *d;
+
+	d = ((PyModuleObject *)m)->md_dict;
+
+	/* First, clear only names starting with a single underscore */
+	pos = 0;
+	while (PyDict_Next(d, &pos, &key, &value)) {
+		if (value != Py_None && PyString_Check(key)) {
+			char *s = PyString_AsString(key);
+			if (s[0] == '_' && s[1] != '_') {
+				if (Py_VerboseFlag > 1)
+				    fprintf(stderr, "#   clear[1] %s\n", s);
+				PyDict_SetItem(d, key, Py_None);
+			}
+		}
+	}
+
+	/* Next, clear all names except for __builtins__ */
+	pos = 0;
+	while (PyDict_Next(d, &pos, &key, &value)) {
+		if (value != Py_None && PyString_Check(key)) {
+			char *s = PyString_AsString(key);
+			if (s[0] != '_' || strcmp(s, "__builtins__") != 0) {
+				if (Py_VerboseFlag > 1)
+				    fprintf(stderr, "#   clear[2] %s\n", s);
+				PyDict_SetItem(d, key, Py_None);
+			}
+		}
+	}
+
+	/* Note: we leave __builtins__ in place, so that destructors
+	   of non-global objects defined in this module can still use
+	   builtins, in particularly 'None'. */
+
+}
+
 /* Methods */
 
 static void
@@ -100,7 +149,7 @@
 	PyModuleObject *m;
 {
 	if (m->md_dict != NULL) {
-		PyDict_Clear(m->md_dict);
+		_PyModule_Clear((PyObject *)m);
 		Py_DECREF(m->md_dict);
 	}
 	free((char *)m);