Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 3121 – Extension Module Initialization and Finalization

Author:
Martin von Löwis <martin at v.loewis.de>
Status:
Final
Type:
Standards Track
Created:
27-Apr-2007
Python-Version:
3.0
Post-History:


Table of Contents

Important

This PEP is a historical document. The up-to-date, canonical documentation can now be found atPyInit_modulename() andPyModuleDef.

×

SeePEP 1 for how to propose changes.

Abstract

Extension module initialization currently has a few deficiencies.There is no cleanup for modules, the entry point name might givenaming conflicts, the entry functions don’t follow the usual callingconvention, and multiple interpreters are not supported well. This PEPaddresses these issues.

Problems

Module Finalization

Currently, extension 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 badfrom a resource management point of view: memory and other resourcesmight get allocated each time initialization is called, but there isno way to reclaim them. As a result, there is currently no way tocompletely release all resources Python has allocated.

Entry point name conflicts

The entry point is currently called init<module>. This might conflictwith other symbols also called init<something>. In particular,initsocket is known to have conflicted in the past (this specificproblem got resolved as a side effect of renaming the module to_socket).

Entry point signature

The entry point is currently a procedure (returning void). Thisdeviates from the usual calling conventions; callers can find outwhether there was an error during initialization only by checkingPyErr_Occurred. The entry point should return a PyObject*, which willbe the module created, or NULL in case of an exception.

Multiple Interpreters

Currently, extension modules share their state across allinterpreters. This allows for undesirable information leakage acrossinterpreters: one script could permanently corrupt objects in anextension module, possibly breaking all scripts in other interpreters.

Specification

The module initialization routines change their signatureto:

PyObject*PyInit_<modulename>()

The initialization routine will be invoked once perinterpreter, when the module is imported. It shouldreturn a new module object each time.

In order to store per-module state in C variables,each module object will contain a block of memorythat is interpreted only by the module. The amountof memory used for the module is specified atthe point of creation of the module.

In addition to the initialization function, a modulemay implement a number of additional callbackfunctions, which are invoked when the module’stp_traverse, tp_clear, and tp_free functions areinvoked, and when the module is reloaded.

The entire module definition is combined in a structPyModuleDef:

structPyModuleDef{PyModuleDef_Basem_base;/*Tobefilledoutbytheinterpreter*/Py_ssize_tm_size;/*Sizeofper-moduledata*/PyMethodDef*m_methods;inquirym_reload;traverseprocm_traverse;inquirym_clear;freefuncm_free;};

Creation of a module is changed to expect an optionalPyModuleDef*. The module state will benull-initialized.

Each module method will be passed the module objectas the first parameter. To access the module data,a function:

void*PyModule_GetState(PyObject*);

will be provided. In addition, to lookup a modulemore efficiently than going through sys.modules,a function:

PyObject*PyState_FindModule(structPyModuleDef*);

will be provided. This lookup function will use anindex located in the m_base field, to find themodule by index, not by name.

As all Python objects should be controlled throughthe Python memory management, usage of “static”type objects is discouraged, unless the type objectitself has no memory-managed state. To simplifydefinition of heap types, a new method:

PyTypeObject*PyType_Copy(PyTypeObject*);

is added.

Example

xxmodule.c would be changed to remove the initxxfunction, 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 featureat one point, and lists the following additional hooks which aren’tcurrently 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 featurehttps://mail.python.org/pipermail/python-3000/2006-April/000726.html

Copyright

This document has been placed in the public domain.


Source:https://github.com/python/peps/blob/main/peps/pep-3121.rst

Last modified:2025-02-01 08:59:27 GMT


[8]ページ先頭

©2009-2025 Movatter.jp