2001-10-12 16:01:43 -03:00
|
|
|
\chapter{Initialization, Finalization, and Threads
|
|
|
|
\label{initialization}}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{Py_Initialize}{}
|
|
|
|
Initialize the Python interpreter. In an application embedding
|
|
|
|
Python, this should be called before using any other Python/C API
|
|
|
|
functions; with the exception of
|
|
|
|
\cfunction{Py_SetProgramName()}\ttindex{Py_SetProgramName()},
|
|
|
|
\cfunction{PyEval_InitThreads()}\ttindex{PyEval_InitThreads()},
|
|
|
|
\cfunction{PyEval_ReleaseLock()}\ttindex{PyEval_ReleaseLock()},
|
|
|
|
and \cfunction{PyEval_AcquireLock()}\ttindex{PyEval_AcquireLock()}.
|
|
|
|
This initializes the table of loaded modules (\code{sys.modules}),
|
|
|
|
and\withsubitem{(in module sys)}{\ttindex{modules}\ttindex{path}}
|
|
|
|
creates the fundamental modules
|
|
|
|
\module{__builtin__}\refbimodindex{__builtin__},
|
|
|
|
\module{__main__}\refbimodindex{__main__} and
|
|
|
|
\module{sys}\refbimodindex{sys}. It also initializes the module
|
|
|
|
search\indexiii{module}{search}{path} path (\code{sys.path}).
|
|
|
|
It does not set \code{sys.argv}; use
|
|
|
|
\cfunction{PySys_SetArgv()}\ttindex{PySys_SetArgv()} for that. This
|
|
|
|
is a no-op when called for a second time (without calling
|
|
|
|
\cfunction{Py_Finalize()}\ttindex{Py_Finalize()} first). There is
|
|
|
|
no return value; it is a fatal error if the initialization fails.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{int}{Py_IsInitialized}{}
|
|
|
|
Return true (nonzero) when the Python interpreter has been
|
|
|
|
initialized, false (zero) if not. After \cfunction{Py_Finalize()}
|
|
|
|
is called, this returns false until \cfunction{Py_Initialize()} is
|
|
|
|
called again.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{Py_Finalize}{}
|
|
|
|
Undo all initializations made by \cfunction{Py_Initialize()} and
|
|
|
|
subsequent use of Python/C API functions, and destroy all
|
|
|
|
sub-interpreters (see \cfunction{Py_NewInterpreter()} below) that
|
|
|
|
were created and not yet destroyed since the last call to
|
|
|
|
\cfunction{Py_Initialize()}. Ideally, this frees all memory
|
|
|
|
allocated by the Python interpreter. This is a no-op when called
|
|
|
|
for a second time (without calling \cfunction{Py_Initialize()} again
|
|
|
|
first). There is no return value; errors during finalization are
|
|
|
|
ignored.
|
|
|
|
|
|
|
|
This function is provided for a number of reasons. An embedding
|
|
|
|
application might want to restart Python without having to restart
|
|
|
|
the application itself. An application that has loaded the Python
|
|
|
|
interpreter from a dynamically loadable library (or DLL) might want
|
|
|
|
to free all memory allocated by Python before unloading the
|
|
|
|
DLL. During a hunt for memory leaks in an application a developer
|
|
|
|
might want to free all memory allocated by Python before exiting
|
|
|
|
from the application.
|
|
|
|
|
|
|
|
\strong{Bugs and caveats:} The destruction of modules and objects in
|
|
|
|
modules is done in random order; this may cause destructors
|
|
|
|
(\method{__del__()} methods) to fail when they depend on other
|
|
|
|
objects (even functions) or modules. Dynamically loaded extension
|
|
|
|
modules loaded by Python are not unloaded. Small amounts of memory
|
|
|
|
allocated by the Python interpreter may not be freed (if you find a
|
|
|
|
leak, please report it). Memory tied up in circular references
|
|
|
|
between objects is not freed. Some memory allocated by extension
|
2003-02-10 15:12:42 -04:00
|
|
|
modules may not be freed. Some extensions may not work properly if
|
2001-10-12 16:01:43 -03:00
|
|
|
their initialization routine is called more than once; this can
|
2003-02-10 15:12:42 -04:00
|
|
|
happen if an application calls \cfunction{Py_Initialize()} and
|
2001-10-12 16:01:43 -03:00
|
|
|
\cfunction{Py_Finalize()} more than once.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyThreadState*}{Py_NewInterpreter}{}
|
|
|
|
Create a new sub-interpreter. This is an (almost) totally separate
|
|
|
|
environment for the execution of Python code. In particular, the
|
|
|
|
new interpreter has separate, independent versions of all imported
|
|
|
|
modules, including the fundamental modules
|
|
|
|
\module{__builtin__}\refbimodindex{__builtin__},
|
|
|
|
\module{__main__}\refbimodindex{__main__} and
|
|
|
|
\module{sys}\refbimodindex{sys}. The table of loaded modules
|
|
|
|
(\code{sys.modules}) and the module search path (\code{sys.path})
|
|
|
|
are also separate. The new environment has no \code{sys.argv}
|
|
|
|
variable. It has new standard I/O stream file objects
|
|
|
|
\code{sys.stdin}, \code{sys.stdout} and \code{sys.stderr} (however
|
|
|
|
these refer to the same underlying \ctype{FILE} structures in the C
|
|
|
|
library).
|
|
|
|
\withsubitem{(in module sys)}{
|
|
|
|
\ttindex{stdout}\ttindex{stderr}\ttindex{stdin}}
|
|
|
|
|
|
|
|
The return value points to the first thread state created in the new
|
|
|
|
sub-interpreter. This thread state is made the current thread
|
|
|
|
state. Note that no actual thread is created; see the discussion of
|
|
|
|
thread states below. If creation of the new interpreter is
|
|
|
|
unsuccessful, \NULL{} is returned; no exception is set since the
|
|
|
|
exception state is stored in the current thread state and there may
|
|
|
|
not be a current thread state. (Like all other Python/C API
|
|
|
|
functions, the global interpreter lock must be held before calling
|
|
|
|
this function and is still held when it returns; however, unlike
|
|
|
|
most other Python/C API functions, there needn't be a current thread
|
|
|
|
state on entry.)
|
|
|
|
|
|
|
|
Extension modules are shared between (sub-)interpreters as follows:
|
|
|
|
the first time a particular extension is imported, it is initialized
|
|
|
|
normally, and a (shallow) copy of its module's dictionary is
|
|
|
|
squirreled away. When the same extension is imported by another
|
|
|
|
(sub-)interpreter, a new module is initialized and filled with the
|
|
|
|
contents of this copy; the extension's \code{init} function is not
|
|
|
|
called. Note that this is different from what happens when an
|
|
|
|
extension is imported after the interpreter has been completely
|
|
|
|
re-initialized by calling
|
|
|
|
\cfunction{Py_Finalize()}\ttindex{Py_Finalize()} and
|
|
|
|
\cfunction{Py_Initialize()}\ttindex{Py_Initialize()}; in that case,
|
|
|
|
the extension's \code{init\var{module}} function \emph{is} called
|
|
|
|
again.
|
|
|
|
|
|
|
|
\strong{Bugs and caveats:} Because sub-interpreters (and the main
|
|
|
|
interpreter) are part of the same process, the insulation between
|
|
|
|
them isn't perfect --- for example, using low-level file operations
|
|
|
|
like \withsubitem{(in module os)}{\ttindex{close()}}
|
|
|
|
\function{os.close()} they can (accidentally or maliciously) affect
|
|
|
|
each other's open files. Because of the way extensions are shared
|
|
|
|
between (sub-)interpreters, some extensions may not work properly;
|
|
|
|
this is especially likely when the extension makes use of (static)
|
|
|
|
global variables, or when the extension manipulates its module's
|
|
|
|
dictionary after its initialization. It is possible to insert
|
|
|
|
objects created in one sub-interpreter into a namespace of another
|
|
|
|
sub-interpreter; this should be done with great care to avoid
|
|
|
|
sharing user-defined functions, methods, instances or classes
|
|
|
|
between sub-interpreters, since import operations executed by such
|
|
|
|
objects may affect the wrong (sub-)interpreter's dictionary of
|
|
|
|
loaded modules. (XXX This is a hard-to-fix bug that will be
|
|
|
|
addressed in a future release.)
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{Py_EndInterpreter}{PyThreadState *tstate}
|
|
|
|
Destroy the (sub-)interpreter represented by the given thread state.
|
|
|
|
The given thread state must be the current thread state. See the
|
|
|
|
discussion of thread states below. When the call returns, the
|
|
|
|
current thread state is \NULL. All thread states associated with
|
|
|
|
this interpreted are destroyed. (The global interpreter lock must
|
|
|
|
be held before calling this function and is still held when it
|
|
|
|
returns.) \cfunction{Py_Finalize()}\ttindex{Py_Finalize()} will
|
|
|
|
destroy all sub-interpreters that haven't been explicitly destroyed
|
|
|
|
at that point.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{Py_SetProgramName}{char *name}
|
|
|
|
This function should be called before
|
|
|
|
\cfunction{Py_Initialize()}\ttindex{Py_Initialize()} is called
|
|
|
|
for the first time, if it is called at all. It tells the
|
|
|
|
interpreter the value of the \code{argv[0]} argument to the
|
|
|
|
\cfunction{main()}\ttindex{main()} function of the program. This is
|
|
|
|
used by \cfunction{Py_GetPath()}\ttindex{Py_GetPath()} and some
|
|
|
|
other functions below to find the Python run-time libraries relative
|
|
|
|
to the interpreter executable. The default value is
|
|
|
|
\code{'python'}. The argument should point to a zero-terminated
|
|
|
|
character string in static storage whose contents will not change
|
|
|
|
for the duration of the program's execution. No code in the Python
|
|
|
|
interpreter will change the contents of this storage.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{char*}{Py_GetProgramName}{}
|
|
|
|
Return the program name set with
|
|
|
|
\cfunction{Py_SetProgramName()}\ttindex{Py_SetProgramName()}, or the
|
|
|
|
default. The returned string points into static storage; the caller
|
|
|
|
should not modify its value.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{char*}{Py_GetPrefix}{}
|
|
|
|
Return the \emph{prefix} for installed platform-independent files.
|
|
|
|
This is derived through a number of complicated rules from the
|
|
|
|
program name set with \cfunction{Py_SetProgramName()} and some
|
|
|
|
environment variables; for example, if the program name is
|
|
|
|
\code{'/usr/local/bin/python'}, the prefix is \code{'/usr/local'}.
|
|
|
|
The returned string points into static storage; the caller should
|
|
|
|
not modify its value. This corresponds to the \makevar{prefix}
|
|
|
|
variable in the top-level \file{Makefile} and the
|
|
|
|
\longprogramopt{prefix} argument to the \program{configure} script
|
|
|
|
at build time. The value is available to Python code as
|
|
|
|
\code{sys.prefix}. It is only useful on \UNIX. See also the next
|
|
|
|
function.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{char*}{Py_GetExecPrefix}{}
|
|
|
|
Return the \emph{exec-prefix} for installed
|
|
|
|
platform-\emph{de}pendent files. This is derived through a number
|
|
|
|
of complicated rules from the program name set with
|
|
|
|
\cfunction{Py_SetProgramName()} and some environment variables; for
|
|
|
|
example, if the program name is \code{'/usr/local/bin/python'}, the
|
|
|
|
exec-prefix is \code{'/usr/local'}. The returned string points into
|
|
|
|
static storage; the caller should not modify its value. This
|
|
|
|
corresponds to the \makevar{exec_prefix} variable in the top-level
|
|
|
|
\file{Makefile} and the \longprogramopt{exec-prefix} argument to the
|
|
|
|
\program{configure} script at build time. The value is available
|
|
|
|
to Python code as \code{sys.exec_prefix}. It is only useful on
|
|
|
|
\UNIX.
|
|
|
|
|
|
|
|
Background: The exec-prefix differs from the prefix when platform
|
|
|
|
dependent files (such as executables and shared libraries) are
|
|
|
|
installed in a different directory tree. In a typical installation,
|
|
|
|
platform dependent files may be installed in the
|
|
|
|
\file{/usr/local/plat} subtree while platform independent may be
|
|
|
|
installed in \file{/usr/local}.
|
|
|
|
|
|
|
|
Generally speaking, a platform is a combination of hardware and
|
|
|
|
software families, e.g. Sparc machines running the Solaris 2.x
|
|
|
|
operating system are considered the same platform, but Intel
|
|
|
|
machines running Solaris 2.x are another platform, and Intel
|
|
|
|
machines running Linux are yet another platform. Different major
|
|
|
|
revisions of the same operating system generally also form different
|
|
|
|
platforms. Non-\UNIX{} operating systems are a different story; the
|
|
|
|
installation strategies on those systems are so different that the
|
|
|
|
prefix and exec-prefix are meaningless, and set to the empty string.
|
|
|
|
Note that compiled Python bytecode files are platform independent
|
|
|
|
(but not independent from the Python version by which they were
|
|
|
|
compiled!).
|
|
|
|
|
|
|
|
System administrators will know how to configure the \program{mount}
|
|
|
|
or \program{automount} programs to share \file{/usr/local} between
|
|
|
|
platforms while having \file{/usr/local/plat} be a different
|
|
|
|
filesystem for each platform.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{char*}{Py_GetProgramFullPath}{}
|
|
|
|
Return the full program name of the Python executable; this is
|
|
|
|
computed as a side-effect of deriving the default module search path
|
|
|
|
from the program name (set by
|
|
|
|
\cfunction{Py_SetProgramName()}\ttindex{Py_SetProgramName()} above).
|
|
|
|
The returned string points into static storage; the caller should
|
|
|
|
not modify its value. The value is available to Python code as
|
|
|
|
\code{sys.executable}.
|
|
|
|
\withsubitem{(in module sys)}{\ttindex{executable}}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{char*}{Py_GetPath}{}
|
|
|
|
\indexiii{module}{search}{path}
|
|
|
|
Return the default module search path; this is computed from the
|
|
|
|
program name (set by \cfunction{Py_SetProgramName()} above) and some
|
|
|
|
environment variables. The returned string consists of a series of
|
|
|
|
directory names separated by a platform dependent delimiter
|
|
|
|
character. The delimiter character is \character{:} on \UNIX,
|
2002-10-10 15:24:54 -03:00
|
|
|
\character{;} on Windows, and \character{\e n} (the \ASCII{}
|
2001-10-12 16:01:43 -03:00
|
|
|
newline character) on Macintosh. The returned string points into
|
|
|
|
static storage; the caller should not modify its value. The value
|
|
|
|
is available to Python code as the list
|
|
|
|
\code{sys.path}\withsubitem{(in module sys)}{\ttindex{path}}, which
|
|
|
|
may be modified to change the future search path for loaded
|
|
|
|
modules.
|
|
|
|
|
|
|
|
% XXX should give the exact rules
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{const char*}{Py_GetVersion}{}
|
|
|
|
Return the version of this Python interpreter. This is a string
|
|
|
|
that looks something like
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
"1.5 (#67, Dec 31 1997, 22:34:28) [GCC 2.7.2.2]"
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
The first word (up to the first space character) is the current
|
|
|
|
Python version; the first three characters are the major and minor
|
|
|
|
version separated by a period. The returned string points into
|
|
|
|
static storage; the caller should not modify its value. The value
|
2003-02-10 15:12:42 -04:00
|
|
|
is available to Python code as \code{sys.version}.
|
2001-10-12 16:01:43 -03:00
|
|
|
\withsubitem{(in module sys)}{\ttindex{version}}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{const char*}{Py_GetPlatform}{}
|
|
|
|
Return the platform identifier for the current platform. On \UNIX,
|
|
|
|
this is formed from the ``official'' name of the operating system,
|
|
|
|
converted to lower case, followed by the major revision number;
|
|
|
|
e.g., for Solaris 2.x, which is also known as SunOS 5.x, the value
|
|
|
|
is \code{'sunos5'}. On Macintosh, it is \code{'mac'}. On Windows,
|
|
|
|
it is \code{'win'}. The returned string points into static storage;
|
|
|
|
the caller should not modify its value. The value is available to
|
|
|
|
Python code as \code{sys.platform}.
|
|
|
|
\withsubitem{(in module sys)}{\ttindex{platform}}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{const char*}{Py_GetCopyright}{}
|
|
|
|
Return the official copyright string for the current Python version,
|
|
|
|
for example
|
|
|
|
|
|
|
|
\code{'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'}
|
|
|
|
|
|
|
|
The returned string points into static storage; the caller should
|
2003-02-10 15:12:42 -04:00
|
|
|
not modify its value. The value is available to Python code as
|
|
|
|
\code{sys.copyright}.
|
2001-10-12 16:01:43 -03:00
|
|
|
\withsubitem{(in module sys)}{\ttindex{copyright}}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{const char*}{Py_GetCompiler}{}
|
|
|
|
Return an indication of the compiler used to build the current
|
|
|
|
Python version, in square brackets, for example:
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
"[GCC 2.7.2.2]"
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
The returned string points into static storage; the caller should
|
|
|
|
not modify its value. The value is available to Python code as part
|
|
|
|
of the variable \code{sys.version}.
|
|
|
|
\withsubitem{(in module sys)}{\ttindex{version}}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{const char*}{Py_GetBuildInfo}{}
|
|
|
|
Return information about the sequence number and build date and time
|
|
|
|
of the current Python interpreter instance, for example
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
"#67, Aug 1 1997, 22:34:28"
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
The returned string points into static storage; the caller should
|
|
|
|
not modify its value. The value is available to Python code as part
|
|
|
|
of the variable \code{sys.version}.
|
|
|
|
\withsubitem{(in module sys)}{\ttindex{version}}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{int}{PySys_SetArgv}{int argc, char **argv}
|
|
|
|
Set \code{sys.argv} based on \var{argc} and \var{argv}. These
|
|
|
|
parameters are similar to those passed to the program's
|
|
|
|
\cfunction{main()}\ttindex{main()} function with the difference that
|
|
|
|
the first entry should refer to the script file to be executed
|
|
|
|
rather than the executable hosting the Python interpreter. If there
|
|
|
|
isn't a script that will be run, the first entry in \var{argv} can
|
|
|
|
be an empty string. If this function fails to initialize
|
|
|
|
\code{sys.argv}, a fatal condition is signalled using
|
|
|
|
\cfunction{Py_FatalError()}\ttindex{Py_FatalError()}.
|
|
|
|
\withsubitem{(in module sys)}{\ttindex{argv}}
|
|
|
|
% XXX impl. doesn't seem consistent in allowing 0/NULL for the params;
|
|
|
|
% check w/ Guido.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
% XXX Other PySys thingies (doesn't really belong in this chapter)
|
|
|
|
|
|
|
|
\section{Thread State and the Global Interpreter Lock
|
|
|
|
\label{threads}}
|
|
|
|
|
|
|
|
\index{global interpreter lock}
|
|
|
|
\index{interpreter lock}
|
|
|
|
\index{lock, interpreter}
|
|
|
|
|
|
|
|
The Python interpreter is not fully thread safe. In order to support
|
|
|
|
multi-threaded Python programs, there's a global lock that must be
|
|
|
|
held by the current thread before it can safely access Python objects.
|
|
|
|
Without the lock, even the simplest operations could cause problems in
|
|
|
|
a multi-threaded program: for example, when two threads simultaneously
|
|
|
|
increment the reference count of the same object, the reference count
|
|
|
|
could end up being incremented only once instead of twice.
|
|
|
|
|
|
|
|
Therefore, the rule exists that only the thread that has acquired the
|
|
|
|
global interpreter lock may operate on Python objects or call Python/C
|
|
|
|
API functions. In order to support multi-threaded Python programs,
|
|
|
|
the interpreter regularly releases and reacquires the lock --- by
|
|
|
|
default, every ten bytecode instructions (this can be changed with
|
|
|
|
\withsubitem{(in module sys)}{\ttindex{setcheckinterval()}}
|
|
|
|
\function{sys.setcheckinterval()}). The lock is also released and
|
|
|
|
reacquired around potentially blocking I/O operations like reading or
|
|
|
|
writing a file, so that other threads can run while the thread that
|
|
|
|
requests the I/O is waiting for the I/O operation to complete.
|
|
|
|
|
|
|
|
The Python interpreter needs to keep some bookkeeping information
|
|
|
|
separate per thread --- for this it uses a data structure called
|
|
|
|
\ctype{PyThreadState}\ttindex{PyThreadState}. This is new in Python
|
|
|
|
1.5; in earlier versions, such state was stored in global variables,
|
|
|
|
and switching threads could cause problems. In particular, exception
|
|
|
|
handling is now thread safe, when the application uses
|
|
|
|
\withsubitem{(in module sys)}{\ttindex{exc_info()}}
|
|
|
|
\function{sys.exc_info()} to access the exception last raised in the
|
|
|
|
current thread.
|
|
|
|
|
|
|
|
There's one global variable left, however: the pointer to the current
|
|
|
|
\ctype{PyThreadState}\ttindex{PyThreadState} structure. While most
|
|
|
|
thread packages have a way to store ``per-thread global data,''
|
|
|
|
Python's internal platform independent thread abstraction doesn't
|
|
|
|
support this yet. Therefore, the current thread state must be
|
|
|
|
manipulated explicitly.
|
|
|
|
|
|
|
|
This is easy enough in most cases. Most code manipulating the global
|
|
|
|
interpreter lock has the following simple structure:
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
Save the thread state in a local variable.
|
|
|
|
Release the interpreter lock.
|
|
|
|
...Do some blocking I/O operation...
|
|
|
|
Reacquire the interpreter lock.
|
|
|
|
Restore the thread state from the local variable.
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
This is so common that a pair of macros exists to simplify it:
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
...Do some blocking I/O operation...
|
|
|
|
Py_END_ALLOW_THREADS
|
|
|
|
\end{verbatim}
|
|
|
|
|
2002-04-09 18:09:42 -03:00
|
|
|
The
|
|
|
|
\csimplemacro{Py_BEGIN_ALLOW_THREADS}\ttindex{Py_BEGIN_ALLOW_THREADS}
|
|
|
|
macro opens a new block and declares a hidden local variable; the
|
|
|
|
\csimplemacro{Py_END_ALLOW_THREADS}\ttindex{Py_END_ALLOW_THREADS}
|
|
|
|
macro closes the block. Another advantage of using these two macros
|
|
|
|
is that when Python is compiled without thread support, they are
|
|
|
|
defined empty, thus saving the thread state and lock manipulations.
|
2001-10-12 16:01:43 -03:00
|
|
|
|
|
|
|
When thread support is enabled, the block above expands to the
|
|
|
|
following code:
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
PyThreadState *_save;
|
|
|
|
|
|
|
|
_save = PyEval_SaveThread();
|
|
|
|
...Do some blocking I/O operation...
|
|
|
|
PyEval_RestoreThread(_save);
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
Using even lower level primitives, we can get roughly the same effect
|
|
|
|
as follows:
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
PyThreadState *_save;
|
|
|
|
|
|
|
|
_save = PyThreadState_Swap(NULL);
|
|
|
|
PyEval_ReleaseLock();
|
|
|
|
...Do some blocking I/O operation...
|
|
|
|
PyEval_AcquireLock();
|
|
|
|
PyThreadState_Swap(_save);
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
There are some subtle differences; in particular,
|
|
|
|
\cfunction{PyEval_RestoreThread()}\ttindex{PyEval_RestoreThread()} saves
|
|
|
|
and restores the value of the global variable
|
|
|
|
\cdata{errno}\ttindex{errno}, since the lock manipulation does not
|
|
|
|
guarantee that \cdata{errno} is left alone. Also, when thread support
|
|
|
|
is disabled,
|
|
|
|
\cfunction{PyEval_SaveThread()}\ttindex{PyEval_SaveThread()} and
|
|
|
|
\cfunction{PyEval_RestoreThread()} don't manipulate the lock; in this
|
|
|
|
case, \cfunction{PyEval_ReleaseLock()}\ttindex{PyEval_ReleaseLock()} and
|
|
|
|
\cfunction{PyEval_AcquireLock()}\ttindex{PyEval_AcquireLock()} are not
|
|
|
|
available. This is done so that dynamically loaded extensions
|
|
|
|
compiled with thread support enabled can be loaded by an interpreter
|
|
|
|
that was compiled with disabled thread support.
|
|
|
|
|
|
|
|
The global interpreter lock is used to protect the pointer to the
|
|
|
|
current thread state. When releasing the lock and saving the thread
|
|
|
|
state, the current thread state pointer must be retrieved before the
|
|
|
|
lock is released (since another thread could immediately acquire the
|
|
|
|
lock and store its own thread state in the global variable).
|
|
|
|
Conversely, when acquiring the lock and restoring the thread state,
|
|
|
|
the lock must be acquired before storing the thread state pointer.
|
|
|
|
|
|
|
|
Why am I going on with so much detail about this? Because when
|
|
|
|
threads are created from C, they don't have the global interpreter
|
|
|
|
lock, nor is there a thread state data structure for them. Such
|
|
|
|
threads must bootstrap themselves into existence, by first creating a
|
|
|
|
thread state data structure, then acquiring the lock, and finally
|
|
|
|
storing their thread state pointer, before they can start using the
|
|
|
|
Python/C API. When they are done, they should reset the thread state
|
|
|
|
pointer, release the lock, and finally free their thread state data
|
|
|
|
structure.
|
|
|
|
|
|
|
|
When creating a thread data structure, you need to provide an
|
|
|
|
interpreter state data structure. The interpreter state data
|
|
|
|
structure hold global data that is shared by all threads in an
|
|
|
|
interpreter, for example the module administration
|
|
|
|
(\code{sys.modules}). Depending on your needs, you can either create
|
|
|
|
a new interpreter state data structure, or share the interpreter state
|
|
|
|
data structure used by the Python main thread (to access the latter,
|
|
|
|
you must obtain the thread state and access its \member{interp} member;
|
|
|
|
this must be done by a thread that is created by Python or by the main
|
|
|
|
thread after Python is initialized).
|
|
|
|
|
2003-03-02 09:17:20 -04:00
|
|
|
Assuming you have access to an interpreter object, the typical idiom
|
|
|
|
for calling into Python from a C thread is
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
PyThreadState *tstate;
|
|
|
|
PyObject *result;
|
|
|
|
|
|
|
|
/* interp is your reference to an interpreter object. */
|
|
|
|
tstate = PyThreadState_New(interp);
|
|
|
|
PyEval_AcquireThread(tstate);
|
|
|
|
|
|
|
|
/* Perform Python actions here. */
|
|
|
|
result = CallSomeFunction();
|
|
|
|
/* evaluate result */
|
|
|
|
|
|
|
|
/* Release the thread. No Python API allowed beyond this point. */
|
|
|
|
PyEval_ReleaseThread(tstate);
|
|
|
|
|
|
|
|
/* You can either delete the thread state, or save it
|
|
|
|
until you need it the next time. */
|
|
|
|
PyThreadState_Delete(tstate);
|
|
|
|
\end{verbatim}
|
2001-10-12 16:01:43 -03:00
|
|
|
|
|
|
|
\begin{ctypedesc}{PyInterpreterState}
|
|
|
|
This data structure represents the state shared by a number of
|
|
|
|
cooperating threads. Threads belonging to the same interpreter
|
|
|
|
share their module administration and a few other internal items.
|
|
|
|
There are no public members in this structure.
|
|
|
|
|
|
|
|
Threads belonging to different interpreters initially share nothing,
|
|
|
|
except process state like available memory, open file descriptors
|
|
|
|
and such. The global interpreter lock is also shared by all
|
|
|
|
threads, regardless of to which interpreter they belong.
|
|
|
|
\end{ctypedesc}
|
|
|
|
|
|
|
|
\begin{ctypedesc}{PyThreadState}
|
|
|
|
This data structure represents the state of a single thread. The
|
|
|
|
only public data member is \ctype{PyInterpreterState
|
|
|
|
*}\member{interp}, which points to this thread's interpreter state.
|
|
|
|
\end{ctypedesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyEval_InitThreads}{}
|
|
|
|
Initialize and acquire the global interpreter lock. It should be
|
|
|
|
called in the main thread before creating a second thread or
|
|
|
|
engaging in any other thread operations such as
|
|
|
|
\cfunction{PyEval_ReleaseLock()}\ttindex{PyEval_ReleaseLock()} or
|
|
|
|
\code{PyEval_ReleaseThread(\var{tstate})}\ttindex{PyEval_ReleaseThread()}.
|
|
|
|
It is not needed before calling
|
|
|
|
\cfunction{PyEval_SaveThread()}\ttindex{PyEval_SaveThread()} or
|
|
|
|
\cfunction{PyEval_RestoreThread()}\ttindex{PyEval_RestoreThread()}.
|
|
|
|
|
|
|
|
This is a no-op when called for a second time. It is safe to call
|
|
|
|
this function before calling
|
|
|
|
\cfunction{Py_Initialize()}\ttindex{Py_Initialize()}.
|
|
|
|
|
|
|
|
When only the main thread exists, no lock operations are needed.
|
|
|
|
This is a common situation (most Python programs do not use
|
|
|
|
threads), and the lock operations slow the interpreter down a bit.
|
|
|
|
Therefore, the lock is not created initially. This situation is
|
|
|
|
equivalent to having acquired the lock: when there is only a single
|
|
|
|
thread, all object accesses are safe. Therefore, when this function
|
|
|
|
initializes the lock, it also acquires it. Before the Python
|
|
|
|
\module{thread}\refbimodindex{thread} module creates a new thread,
|
|
|
|
knowing that either it has the lock or the lock hasn't been created
|
|
|
|
yet, it calls \cfunction{PyEval_InitThreads()}. When this call
|
|
|
|
returns, it is guaranteed that the lock has been created and that it
|
|
|
|
has acquired it.
|
|
|
|
|
|
|
|
It is \strong{not} safe to call this function when it is unknown
|
|
|
|
which thread (if any) currently has the global interpreter lock.
|
|
|
|
|
|
|
|
This function is not available when thread support is disabled at
|
|
|
|
compile time.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyEval_AcquireLock}{}
|
|
|
|
Acquire the global interpreter lock. The lock must have been
|
|
|
|
created earlier. If this thread already has the lock, a deadlock
|
|
|
|
ensues. This function is not available when thread support is
|
|
|
|
disabled at compile time.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyEval_ReleaseLock}{}
|
|
|
|
Release the global interpreter lock. The lock must have been
|
|
|
|
created earlier. This function is not available when thread support
|
|
|
|
is disabled at compile time.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyEval_AcquireThread}{PyThreadState *tstate}
|
|
|
|
Acquire the global interpreter lock and then set the current thread
|
|
|
|
state to \var{tstate}, which should not be \NULL. The lock must
|
|
|
|
have been created earlier. If this thread already has the lock,
|
|
|
|
deadlock ensues. This function is not available when thread support
|
|
|
|
is disabled at compile time.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyEval_ReleaseThread}{PyThreadState *tstate}
|
|
|
|
Reset the current thread state to \NULL{} and release the global
|
|
|
|
interpreter lock. The lock must have been created earlier and must
|
|
|
|
be held by the current thread. The \var{tstate} argument, which
|
|
|
|
must not be \NULL, is only used to check that it represents the
|
|
|
|
current thread state --- if it isn't, a fatal error is reported.
|
|
|
|
This function is not available when thread support is disabled at
|
|
|
|
compile time.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyThreadState*}{PyEval_SaveThread}{}
|
|
|
|
Release the interpreter lock (if it has been created and thread
|
|
|
|
support is enabled) and reset the thread state to \NULL, returning
|
|
|
|
the previous thread state (which is not \NULL). If the lock has
|
|
|
|
been created, the current thread must have acquired it. (This
|
|
|
|
function is available even when thread support is disabled at
|
|
|
|
compile time.)
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyEval_RestoreThread}{PyThreadState *tstate}
|
|
|
|
Acquire the interpreter lock (if it has been created and thread
|
|
|
|
support is enabled) and set the thread state to \var{tstate}, which
|
|
|
|
must not be \NULL. If the lock has been created, the current thread
|
|
|
|
must not have acquired it, otherwise deadlock ensues. (This
|
|
|
|
function is available even when thread support is disabled at
|
|
|
|
compile time.)
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
The following macros are normally used without a trailing semicolon;
|
|
|
|
look for example usage in the Python source distribution.
|
|
|
|
|
|
|
|
\begin{csimplemacrodesc}{Py_BEGIN_ALLOW_THREADS}
|
|
|
|
This macro expands to
|
|
|
|
\samp{\{ PyThreadState *_save; _save = PyEval_SaveThread();}.
|
|
|
|
Note that it contains an opening brace; it must be matched with a
|
2002-04-09 18:09:42 -03:00
|
|
|
following \csimplemacro{Py_END_ALLOW_THREADS} macro. See above for
|
|
|
|
further discussion of this macro. It is a no-op when thread support
|
|
|
|
is disabled at compile time.
|
2001-10-12 16:01:43 -03:00
|
|
|
\end{csimplemacrodesc}
|
|
|
|
|
|
|
|
\begin{csimplemacrodesc}{Py_END_ALLOW_THREADS}
|
|
|
|
This macro expands to \samp{PyEval_RestoreThread(_save); \}}.
|
|
|
|
Note that it contains a closing brace; it must be matched with an
|
2002-04-09 18:09:42 -03:00
|
|
|
earlier \csimplemacro{Py_BEGIN_ALLOW_THREADS} macro. See above for
|
|
|
|
further discussion of this macro. It is a no-op when thread support
|
|
|
|
is disabled at compile time.
|
2001-10-12 16:01:43 -03:00
|
|
|
\end{csimplemacrodesc}
|
|
|
|
|
|
|
|
\begin{csimplemacrodesc}{Py_BLOCK_THREADS}
|
|
|
|
This macro expands to \samp{PyEval_RestoreThread(_save);}: it is
|
2002-04-09 18:09:42 -03:00
|
|
|
equivalent to \csimplemacro{Py_END_ALLOW_THREADS} without the
|
|
|
|
closing brace. It is a no-op when thread support is disabled at
|
|
|
|
compile time.
|
2001-10-12 16:01:43 -03:00
|
|
|
\end{csimplemacrodesc}
|
|
|
|
|
|
|
|
\begin{csimplemacrodesc}{Py_UNBLOCK_THREADS}
|
|
|
|
This macro expands to \samp{_save = PyEval_SaveThread();}: it is
|
2002-04-09 18:09:42 -03:00
|
|
|
equivalent to \csimplemacro{Py_BEGIN_ALLOW_THREADS} without the
|
|
|
|
opening brace and variable declaration. It is a no-op when thread
|
|
|
|
support is disabled at compile time.
|
2001-10-12 16:01:43 -03:00
|
|
|
\end{csimplemacrodesc}
|
|
|
|
|
|
|
|
All of the following functions are only available when thread support
|
|
|
|
is enabled at compile time, and must be called only when the
|
|
|
|
interpreter lock has been created.
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyInterpreterState*}{PyInterpreterState_New}{}
|
|
|
|
Create a new interpreter state object. The interpreter lock need
|
|
|
|
not be held, but may be held if it is necessary to serialize calls
|
|
|
|
to this function.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyInterpreterState_Clear}{PyInterpreterState *interp}
|
|
|
|
Reset all information in an interpreter state object. The
|
|
|
|
interpreter lock must be held.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyInterpreterState_Delete}{PyInterpreterState *interp}
|
|
|
|
Destroy an interpreter state object. The interpreter lock need not
|
|
|
|
be held. The interpreter state must have been reset with a previous
|
|
|
|
call to \cfunction{PyInterpreterState_Clear()}.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyThreadState*}{PyThreadState_New}{PyInterpreterState *interp}
|
|
|
|
Create a new thread state object belonging to the given interpreter
|
|
|
|
object. The interpreter lock need not be held, but may be held if
|
|
|
|
it is necessary to serialize calls to this function.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyThreadState_Clear}{PyThreadState *tstate}
|
|
|
|
Reset all information in a thread state object. The interpreter lock
|
|
|
|
must be held.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyThreadState_Delete}{PyThreadState *tstate}
|
|
|
|
Destroy a thread state object. The interpreter lock need not be
|
|
|
|
held. The thread state must have been reset with a previous call to
|
|
|
|
\cfunction{PyThreadState_Clear()}.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyThreadState*}{PyThreadState_Get}{}
|
|
|
|
Return the current thread state. The interpreter lock must be
|
|
|
|
held. When the current thread state is \NULL, this issues a fatal
|
|
|
|
error (so that the caller needn't check for \NULL).
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyThreadState*}{PyThreadState_Swap}{PyThreadState *tstate}
|
|
|
|
Swap the current thread state with the thread state given by the
|
|
|
|
argument \var{tstate}, which may be \NULL. The interpreter lock
|
|
|
|
must be held.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyObject*}{PyThreadState_GetDict}{}
|
|
|
|
Return a dictionary in which extensions can store thread-specific
|
|
|
|
state information. Each extension should use a unique key to use to
|
|
|
|
store state in the dictionary. If this function returns \NULL, an
|
|
|
|
exception has been raised and the caller should allow it to
|
2002-12-06 18:42:13 -04:00
|
|
|
propagate.
|
2001-10-12 16:01:43 -03:00
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
|
|
|
|
\section{Profiling and Tracing \label{profiling}}
|
|
|
|
|
|
|
|
\sectionauthor{Fred L. Drake, Jr.}{fdrake@acm.org}
|
|
|
|
|
|
|
|
The Python interpreter provides some low-level support for attaching
|
|
|
|
profiling and execution tracing facilities. These are used for
|
|
|
|
profiling, debugging, and coverage analysis tools.
|
|
|
|
|
|
|
|
Starting with Python 2.2, the implementation of this facility was
|
|
|
|
substantially revised, and an interface from C was added. This C
|
|
|
|
interface allows the profiling or tracing code to avoid the overhead
|
|
|
|
of calling through Python-level callable objects, making a direct C
|
|
|
|
function call instead. The essential attributes of the facility have
|
|
|
|
not changed; the interface allows trace functions to be installed
|
|
|
|
per-thread, and the basic events reported to the trace function are
|
|
|
|
the same as had been reported to the Python-level trace functions in
|
|
|
|
previous versions.
|
|
|
|
|
|
|
|
\begin{ctypedesc}[Py_tracefunc]{int (*Py_tracefunc)(PyObject *obj,
|
|
|
|
PyFrameObject *frame, int what,
|
|
|
|
PyObject *arg)}
|
|
|
|
The type of the trace function registered using
|
|
|
|
\cfunction{PyEval_SetProfile()} and \cfunction{PyEval_SetTrace()}.
|
|
|
|
The first parameter is the object passed to the registration
|
|
|
|
function as \var{obj}, \var{frame} is the frame object to which the
|
|
|
|
event pertains, \var{what} is one of the constants
|
|
|
|
\constant{PyTrace_CALL}, \constant{PyTrace_EXCEPT},
|
|
|
|
\constant{PyTrace_LINE} or \constant{PyTrace_RETURN}, and \var{arg}
|
|
|
|
depends on the value of \var{what}:
|
|
|
|
|
|
|
|
\begin{tableii}{l|l}{constant}{Value of \var{what}}{Meaning of \var{arg}}
|
|
|
|
\lineii{PyTrace_CALL}{Always \NULL.}
|
|
|
|
\lineii{PyTrace_EXCEPT}{Exception information as returned by
|
|
|
|
\function{sys.exc_info()}.}
|
|
|
|
\lineii{PyTrace_LINE}{Always \NULL.}
|
|
|
|
\lineii{PyTrace_RETURN}{Value being returned to the caller.}
|
|
|
|
\end{tableii}
|
|
|
|
\end{ctypedesc}
|
|
|
|
|
|
|
|
\begin{cvardesc}{int}{PyTrace_CALL}
|
|
|
|
The value of the \var{what} parameter to a \ctype{Py_tracefunc}
|
|
|
|
function when a new call to a function or method is being reported,
|
|
|
|
or a new entry into a generator. Note that the creation of the
|
|
|
|
iterator for a generator function is not reported as there is no
|
|
|
|
control transfer to the Python bytecode in the corresponding frame.
|
|
|
|
\end{cvardesc}
|
|
|
|
|
|
|
|
\begin{cvardesc}{int}{PyTrace_EXCEPT}
|
|
|
|
The value of the \var{what} parameter to a \ctype{Py_tracefunc}
|
2001-10-16 16:23:55 -03:00
|
|
|
function when an exception has been raised. The callback function
|
|
|
|
is called with this value for \var{what} when after any bytecode is
|
|
|
|
processed after which the exception becomes set within the frame
|
|
|
|
being executed. The effect of this is that as exception propogation
|
|
|
|
causes the Python stack to unwind, the callback is called upon
|
2002-12-06 18:42:13 -04:00
|
|
|
return to each frame as the exception propagates. Only trace
|
2001-10-16 16:23:55 -03:00
|
|
|
functions receives these events; they are not needed by the
|
|
|
|
profiler.
|
2001-10-12 16:01:43 -03:00
|
|
|
\end{cvardesc}
|
|
|
|
|
|
|
|
\begin{cvardesc}{int}{PyTrace_LINE}
|
|
|
|
The value passed as the \var{what} parameter to a trace function
|
|
|
|
(but not a profiling function) when a line-number event is being
|
|
|
|
reported.
|
|
|
|
\end{cvardesc}
|
|
|
|
|
|
|
|
\begin{cvardesc}{int}{PyTrace_RETURN}
|
|
|
|
The value for the \var{what} parameter to \ctype{Py_tracefunc}
|
|
|
|
functions when a call is returning without propogating an exception.
|
|
|
|
\end{cvardesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyEval_SetProfile}{Py_tracefunc func, PyObject *obj}
|
|
|
|
Set the profiler function to \var{func}. The \var{obj} parameter is
|
|
|
|
passed to the function as its first parameter, and may be any Python
|
|
|
|
object, or \NULL. If the profile function needs to maintain state,
|
|
|
|
using a different value for \var{obj} for each thread provides a
|
|
|
|
convenient and thread-safe place to store it. The profile function
|
|
|
|
is called for all monitored events except the line-number events.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{void}{PyEval_SetTrace}{Py_tracefunc func, PyObject *obj}
|
|
|
|
Set the the tracing function to \var{func}. This is similar to
|
|
|
|
\cfunction{PyEval_SetProfile()}, except the tracing function does
|
|
|
|
receive line-number events.
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
|
|
|
|
\section{Advanced Debugger Support \label{advanced-debugging}}
|
|
|
|
\sectionauthor{Fred L. Drake, Jr.}{fdrake@acm.org}
|
|
|
|
|
|
|
|
These functions are only intended to be used by advanced debugging
|
|
|
|
tools.
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyInterpreterState*}{PyInterpreterState_Head}{}
|
|
|
|
Return the interpreter state object at the head of the list of all
|
|
|
|
such objects.
|
|
|
|
\versionadded{2.2}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyInterpreterState*}{PyInterpreterState_Next}{PyInterpreterState *interp}
|
|
|
|
Return the next interpreter state object after \var{interp} from the
|
|
|
|
list of all such objects.
|
|
|
|
\versionadded{2.2}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyThreadState *}{PyInterpreterState_ThreadHead}{PyInterpreterState *interp}
|
|
|
|
Return the a pointer to the first \ctype{PyThreadState} object in
|
|
|
|
the list of threads associated with the interpreter \var{interp}.
|
|
|
|
\versionadded{2.2}
|
|
|
|
\end{cfuncdesc}
|
|
|
|
|
|
|
|
\begin{cfuncdesc}{PyThreadState*}{PyThreadState_Next}{PyThreadState *tstate}
|
|
|
|
Return the next thread state object after \var{tstate} from the list
|
|
|
|
of all such objects belonging to the same \ctype{PyInterpreterState}
|
|
|
|
object.
|
|
|
|
\versionadded{2.2}
|
|
|
|
\end{cfuncdesc}
|