[Python-checkins] r54997 - peps/trunk/pep-0000.txt peps/trunk/pep-3121.txt

martin.v.loewis python-checkins at python.org
Fri Apr 27 10:27:25 CEST 2007


Author: martin.v.loewis
Date: Fri Apr 27 10:27:24 2007
New Revision: 54997

Added:
   peps/trunk/pep-3121.txt   (contents, props changed)
Modified:
   peps/trunk/pep-0000.txt
Log:
Add PEP 3121.


Modified: peps/trunk/pep-0000.txt
==============================================================================
--- peps/trunk/pep-0000.txt	(original)
+++ peps/trunk/pep-0000.txt	Fri Apr 27 10:27:24 2007
@@ -118,6 +118,7 @@
  S  3118  Revising the buffer protocol                 Oliphant, Banks
  S  3119  Introducing Abstract Base Classes            GvR, Talin
  S  3120  Using UTF-8 as the default source encoding   von Löwis
+ S  3121  Module Initialization and finalization       von Löwis
  S  3141  A Type Hierarchy for Numbers                 Yasskin
 
  Finished PEPs (done, implemented in Subversion)
@@ -476,6 +477,7 @@
  S  3118  Revising the buffer protocol                 Oliphant, Banks
  S  3119  Introducing Abstract Base Classes            GvR, Talin
  S  3120  Using UTF-8 as the default source encoding   von Löwis
+ S  3121  Module Initialization and finalization       von Löwis
  S  3141  A Type Hierarchy for Numbers                 Yasskin
 
 

Added: peps/trunk/pep-3121.txt
==============================================================================
--- (empty file)
+++ peps/trunk/pep-3121.txt	Fri Apr 27 10:27:24 2007
@@ -0,0 +1,220 @@
+PEP: 3121
+Title: Module Initialization and finalization
+Version: $Revision: 54994 $
+Last-Modified: $Date: 2007-04-27 08:34:37 +0200 (Fr, 27 Apr 2007) $
+Author: Martin v. Löwis <martin at v.loewis.de>
+Status: Draft
+Type: Standards Track
+Content-Type: text/x-rst
+Created: 27-Apr-2007
+Python-Version: 3.0
+Post-History:
+
+Abstract
+========
+
+Module initialization currently has a few deficiencies.  There is no
+cleanup for modules, the entry point name might give naming conflicts,
+the entry functions don't follow the usual calling convention, and
+multiple interpreters are not supported well. This PEP addresses these
+issues.
+
+Module Finalization
+===================
+
+Currently, C modules are initialized usually once and then "live"
+forever. The only exception is when Py_Finalize() is called: then
+the initialization routine is invoked a second time. This is bad
+from a resource management point of view: memory and other resources
+might get allocated each time initialization is called, but there
+is no way to reclaim them. As a result, there is currently no
+way to completely release all resources Python has allocated.
+
+Entry point name conflicts
+==========================
+
+The entry point is currently called init<module>. This might conflict
+with other symbols also called init<something>. In particular,
+initsocket is known to have conflicted in the past (this specific
+problem got resolved as a side effect of renaming the module to
+_socket).
+
+Entry point signature
+=====================
+
+The entry point is currently a procedure (returning void).  This
+deviates from the usual calling conventions; callers can find out
+whether there was an error during initialization only by checking
+PyErr_Occurred. The entry point should return a PyObject*, which will
+be the module created, or NULL in case of an exception.
+
+Multiple Interpreters
+=====================
+
+Currently, extension modules share their state across all
+interpreters. This allows for undesirable information leakage across
+interpreters: one script could permanently corrupt objects in an
+extension module, possibly breaking all scripts in other interpreters.
+
+Specification
+=============
+
+The module initialization routines change their signature
+to::
+
+  PyObject *PyInit_<modulename>()
+
+The initialization routine will be invoked once per
+interpreter, when the module is imported. It should
+return a new module object each time.
+
+In order to store per-module state in C variables,
+each module object will contain a block of memory
+that is interpreted only by the module. The amount
+of memory used for the module is specified at
+the point of creation of the module.
+
+In addition to the initialization function, a module
+may implement a number of additional callback 
+function, which are invoked when the module's
+tp_traverse, tp_clear, and tp_free functions are
+invoked, and when the module is reloaded.
+
+The entire module definition is combined in a struct
+PyModuleDef::
+
+  struct PyModuleDef{
+    PyModuleDef_Base m_base;  /* To be filled out by the interpreter */
+    Py_ssize_t m_size; /* Size of per-module data */
+    PyMethodDef *m_methods;
+    inquiry m_reload;
+    traverseproc m_traverse;
+    inquiry m_clear;
+    freefunc m_free;
+  };
+
+Creation of a module is changed to expect an optional
+PyModuleDef*. The module state will be 
+null-initialized.
+
+Each module method with be passed the module object
+as the first parameter. To access the module data,
+a function::
+
+  void* PyModule_GetData(PyObject*);
+
+will be provided. In addition, to lookup a module
+more efficiently than going through sys.modules,
+a function::
+
+  PyObject* PyState_FindModule(struct PyModuleDef*);
+
+will be provided. This lookup function will use an
+index located in the m_base field, to find the
+module by index, not by name.
+
+As all Python objects should be controlled through
+the Python memory management, usage of "static"
+type objects is discouraged, unless the type object
+itself has no memory-managed state. To simplify
+definition of heap types, a new method::
+
+  PyTypeObject* PyType_Copy(PyTypeObject*);
+
+is added.
+
+Example
+=======
+
+xxmodule.c would be changed to remove the initxx
+function, and add the following code instead::
+
+  struct xxstate{
+    PyObject *ErrorObject;
+    PyObject *Xxo_Type;
+  };
+
+  #define xxstate(o) ((struct xxstate*)PyModule_GetState(o))
+
+  static int xx_traverse(PyObject *m, visitproc v,
+                         void *arg)
+  {
+    Py_VISIT(xxstate(m)->ErrorObject);
+    Py_VISIT(xxstate(m)->Xxo_Type);
+    return 0;
+  }
+
+  static int xx_clear(PyObject *m)
+  {
+    Py_CLEAR(xxstate(m)->ErrorObject);
+    Py_CLEAR(xxstate(m)->Xxo_Type);
+    return 0;
+  }
+
+  static struct PyModuleDef xxmodule = {
+    {}, /* m_base */
+    sizeof(struct xxstate),
+    &xx_methods,
+    0,  /* m_reload */
+    xx_traverse,
+    xx_clear,
+    0,  /* m_free - not needed, since all is done in m_clear */
+  }
+
+  PyObject*
+  PyInit_xx()
+  {
+    PyObject *res = PyModule_New("xx", &xxmodule);
+    if (!res) return NULL;
+    xxstate(res)->ErrorObject = PyErr_NewException("xx.error, NULL, NULL);
+    if (!xxstate(res)->ErrorObject) {
+      Py_DECREF(res);
+      return NULL;
+    }
+    xxstate(res)->XxoType = PyType_Copy(&Xxo_Type);
+    if (!xxstate(res)->Xxo_Type) {
+      Py_DECREF(res);
+      return NULL;
+    }
+    return res;
+  }
+    
+
+Discussion
+==========
+
+Tim Peters reports in [1]_ that PythonLabs considered such a feature
+at one point, and lists the following additional hooks which aren't
+currently supported in this PEP:
+
+ * when the module object is deleted from sys.modules
+
+ * when Py_Finalize is called
+
+ * when Python exits
+
+ * when the Python DLL is unloaded (Windows only)
+
+
+References
+==========
+
+.. [1] Tim Peters, reporting earlier conversation about such a feature
+   http://mail.python.org/pipermail/python-3000/2006-April/000726.html
+
+
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+
+..
+   Local Variables:
+   mode: indented-text
+   indent-tabs-mode: nil
+   sentence-end-double-space: t
+   fill-column: 70
+   coding: utf-8
+   End:


More information about the Python-checkins mailing list