初始化，最终化和线程
********************

请参阅 Python 初始化配置 。


在Python初始化之前
==================

在一个植入了 Python 的应用程序中，"Py_Initialize()" 函数必须在任何其他
Python/C API 函数之前被调用；例外的只有个别函数和 全局配置变量。

在初始化Python之前，可以安全地调用以下函数：

* 配置函数：

  * "PyImport_AppendInittab()"

  * "PyImport_ExtendInittab()"

  * "PyInitFrozenExtensions()"

  * "PyMem_SetAllocator()"

  * "PyMem_SetupDebugHooks()"

  * "PyObject_SetArenaAllocator()"

  * "Py_SetPath()"

  * "Py_SetProgramName()"

  * "Py_SetPythonHome()"

  * "Py_SetStandardStreamEncoding()"

  * "PySys_AddWarnOption()"

  * "PySys_AddXOption()"

  * "PySys_ResetWarnOptions()"

* 信息函数：

  * "Py_IsInitialized()"

  * "PyMem_GetAllocator()"

  * "PyObject_GetArenaAllocator()"

  * "Py_GetBuildInfo()"

  * "Py_GetCompiler()"

  * "Py_GetCopyright()"

  * "Py_GetPlatform()"

  * "Py_GetVersion()"

* 工具

  * "Py_DecodeLocale()"

* 内存分配器：

  * "PyMem_RawMalloc()"

  * "PyMem_RawRealloc()"

  * "PyMem_RawCalloc()"

  * "PyMem_RawFree()"

注解:

  以下函数 **不应该** 在 "Py_Initialize()": "Py_EncodeLocale()",
  "Py_GetPath()", "Py_GetPrefix()", "Py_GetExecPrefix()",
  "Py_GetProgramFullPath()", "Py_GetPythonHome()",
  "Py_GetProgramName()" 和 "PyEval_InitThreads()" 前调用。


全局配置变量
============

Python 有负责控制全局配置中不同特性和选项的变量。这些标志默认被 命令行
选项。

当一个选项设置一个旗标时，该旗标的值将是设置选项的次数。 例如，"-b" 会
将 "Py_BytesWarningFlag" 设为 1 而 "-bb" 会将 "Py_BytesWarningFlag" 设
为 2.

int Py_BytesWarningFlag

   当将 "bytes" 或 "bytearray" 与 "str" 比较或者将 "bytes" 与 "int" 比
   较时发出警告。 如果大于等于 "2" 则报错。

   由 "-b" 选项设置。

int Py_DebugFlag

   开启解析器调试输出（限专家使用，依赖于编译选项）。

   由 "-d" 选项和 "PYTHONDEBUG" 环境变量设置。

int Py_DontWriteBytecodeFlag

   如果设置为非零, Python 不会在导入源代码时尝试写入 ".pyc" 文件

   由 "-B" 选项和 "PYTHONDONTWRITEBYTECODE" 环境变量设置。

int Py_FrozenFlag

   当在 "Py_GetPath()" 中计算模块搜索路径时屏蔽错误消息。

   由 "_freeze_importlib" 和 "frozenmain" 程序使用的私有旗标。

int Py_HashRandomizationFlag

   如果 "PYTHONHASHSEED" 环境变量被设为非空字符串则设为 "1"。

   如果该旗标为非零值，则读取 "PYTHONHASHSEED" 环境变量来初始化加密哈
   希种子。

int Py_IgnoreEnvironmentFlag

   忽略所有 "PYTHON*" 环境变量，例如，已设置的 "PYTHONPATH" 和
   "PYTHONHOME"。

   由 "-E"  和 "-I" 选项设置。

int Py_InspectFlag

   当将脚本作为第一个参数传入或是使用了 "-c" 选项时，则会在执行该脚本
   或命令后进入交互模式，即使在 "sys.stdin" 并非一个终端时也是如此。

   由 "-i" 选项和 "PYTHONINSPECT" 环境变量设置。

int Py_InteractiveFlag

   由 "-i" 选项设置。

int Py_IsolatedFlag

   以隔离模式运行 Python. 在隔离模式下 "sys.path" 将不包含脚本的目录或
   用户的 site-packages 目录。

   由 "-I" 选项设置。

   3.4 新版功能.

int Py_LegacyWindowsFSEncodingFlag

   If the flag is non-zero, use the "mbcs" encoding instead of the
   UTF-8 encoding for the filesystem encoding.

   如果 "PYTHONLEGACYWINDOWSFSENCODING" 环境变量被设为非空字符串则设为
   "1"。

   更多详情请参阅 **PEP 529**。

   可用性: Windows。

int Py_LegacyWindowsStdioFlag

   如果该旗标为非零值，则会使用 "io.FileIO" 而不是 "WindowsConsoleIO"
   作为 "sys" 的标准流。

   如果 "PYTHONLEGACYWINDOWSSTDIO" 环境变量被设为非空字符串则设为 "1"
   。

   有关更多详细信息，请参阅 **PEP 528**。

   可用性: Windows。

int Py_NoSiteFlag

   禁用 "site" 的导入及其所附带的基于站点对 "sys.path" 的操作。 如果
   "site" 会在稍后被显式地导入也会禁用这些操作 (如果你希望触发它们则应
   调用 "site.main()")。

   由 "-S" 选项设置。

int Py_NoUserSiteDirectory

   不要将 "用户 site-packages 目录" 添加到 "sys.path"。

   由 "-s" 和 "-I" 选项以及 "PYTHONNOUSERSITE" 环境变量设置。

int Py_OptimizeFlag

   由 "-O" 选项和 "PYTHONOPTIMIZE" 环境变量设置。

int Py_QuietFlag

   即使在交互模式下也不显示版权和版本信息。

   由 "-q" 选项设置。

   3.2 新版功能.

int Py_UnbufferedStdioFlag

   强制 stdout 和 stderr 流不带缓冲。

   由 "-u" 选项和 "PYTHONUNBUFFERED" 环境变量设置。

int Py_VerboseFlag

   每次初始化模块时打印一条消息，显示加载模块的位置（文件名或内置模块
   ）。 如果大于或等于 "2"，则为搜索模块时检查的每个文件打印一条消息。
   此外还会在退出时提供模块清理信息。

   由 "-v" 选项和 "PYTHONVERBOSE" 环境变量设置。


初始化和最终化解释器
====================

void Py_Initialize()

   初始化 Python 解释器。 在嵌入 Python 的应用程序中，它应当在使用任何
   其他 Python/C API 函数之前被调用；请参阅 在 Python 初始化之前 了解
   少数的例外情况。

   这将初始化已加载模块表 ("sys.modules")，并创建基本模块 "builtins"、
   "__main__" 和 "sys"。 它还会初始化模块搜索路径 ("sys.path")。 它不
   会设置 "sys.argv"；如有需要请使用 "PySys_SetArgvEx()"。 当第二次调
   用时 (在未事先调用 "Py_FinalizeEx()" 的情况下) 将不会执行任何操作。
   它没有返回值；如果初始化失败则会发生致命错误。

   注解:

     在 Windows 上，将控制台模式从 "O_TEXT" 改为 "O_BINARY"，这还将影
     响使用 C 运行时的非 Python 的控制台使用。

void Py_InitializeEx(int initsigs)

   如果 *initsigs* 为 "1" 则该函数的工作方式与 "Py_Initialize()" 类似
   。 如果 *initsigs* 为 "0"，它将跳过信号处理器的初始化注册，这在嵌入
   Python 时可能会很有用处。

int Py_IsInitialized()

   如果 Python 解释器已初始化，则返回真值（非零）；否则返回假值（零）
   。 在调用 "Py_FinalizeEx()" 之后，此函数将返回假值直到
   "Py_Initialize()" 再次被调用。

int Py_FinalizeEx()

   撤销 "Py_Initialize()" 所做的所有初始化操作和后续对 Python/C API 函
   数的使用，并销毁自上次调用 "Py_Initialize()" 以来创建但尚未销毁的所
   有子解释器（参见下文 "Py_NewInterpreter()" 一节)。 在理想情况下，这
   会释放 Python 解释器分配的所有内存。 当第二次调用时（在未再次调用
   "Py_Initialize()" 的情况下），这将不执行任何操作。 正常情况下返回值
   是 "0"。 如果在最终化（刷新缓冲数据）过程中出现错误，则返回 "-1"。

   提供此函数的原因有很多。嵌入应用程序可能希望重新启动Python，而不必
   重新启动应用程序本身。从动态可加载库（或DLL）加载Python解释器的应用
   程序可能希望在卸载DLL之前释放Python分配的所有内存。在搜索应用程序内
   存泄漏的过程中，开发人员可能希望在退出应用程序之前释放Python分配的
   所有内存。

   **Bugs and caveats:** The destruction of modules and objects in
   modules is done in random order; this may cause destructors
   ("__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
   modules may not be freed.  Some extensions may not work properly if
   their initialization routine is called more than once; this can
   happen if an application calls "Py_Initialize()" and
   "Py_FinalizeEx()" more than once.

   引发一个不带参数的 审计事件 "cpython._PySys_ClearAuditHooks"。

   3.6 新版功能.

void Py_Finalize()

   这是一个不考虑返回值的 "Py_FinalizeEx()" 的向下兼容版本。


进程级参数
==========

int Py_SetStandardStreamEncoding(const char *encoding, const char *errors)

   如果要调用该函数，应当在 "Py_Initialize()" 之前调用。 它指定了标准
   IO 使用的编码格式和错误处理方式，其含义与 "str.encode()" 中的相同。

   它覆盖了 "PYTHONIOENCODING" 的值，并允许嵌入代码以便在环境变量不起
   作用时控制 IO 编码格式。

   *encoding* 和/或 *errors* 可以为 "NULL" 以使用 "PYTHONIOENCODING"
   和/或默认值（取决于其他设置）。

   请注意无论是否有此设置（或任何其他设置），"sys.stderr" 都会使用
   "backslashreplace" 错误处理器。

   如果调用了 "Py_FinalizeEx()"，则需要再次调用该函数以便影响对
   "Py_Initialize()" 的后续调用。

   成功时返回 "0"，出错时返回非零值（例如在解释器已被初始化后再调用）
   。

   3.4 新版功能.

void Py_SetProgramName(const wchar_t *name)

   如果要调用该函数，应当在首次调用 "Py_Initialize()" 之前调用它。 它
   将告诉解释器程序的 "main()" 函数的 "argv[0]" 参数的值（转换为宽字符
   ）。 "Py_GetPath()" 和下面的某些其他函数会使用它在相对于解释器的位
   置上查找可执行文件的 Python 运行时库。 默认值是 "'python'"。 参数应
   当指向静态存储中的一个以零值结束的宽字符串，其内容在程序执行期间不
   会发生改变。 Python 解释器中的任何代码都不会改变该存储的内容。

   Use "Py_DecodeLocale()" to decode a bytes string to get a "wchar_*"
   string.

wchar* Py_GetProgramName()

   返回用 "Py_SetProgramName()" 设置的程序名称，或默认的名称。 返回的
   字符串指向静态存储；调用者不应修改其值。

wchar_t* Py_GetPrefix()

   Return the *prefix* for installed platform-independent files. This
   is derived through a number of complicated rules from the program
   name set with "Py_SetProgramName()" and some environment variables;
   for example, if the program name is "'/usr/local/bin/python'", the
   prefix is "'/usr/local'". The returned string points into static
   storage; the caller should not modify its value.  This corresponds
   to the **prefix** variable in the top-level "Makefile" and the "--
   prefix" argument to the **configure** script at build time.  The
   value is available to Python code as "sys.prefix". It is only
   useful on Unix.  See also the next function.

wchar_t* Py_GetExecPrefix()

   返回针对已安装的 *依赖于* 平台文件的 *exec-prefix*。 这是通过基于使
   用 "Py_SetProgramName()" 设置的程序名称和某些环境变量所派生的一系列
   复杂规则获得的；举例来说，如果程序名称为 "'/usr/local/bin/python'"
   ，则 exec-prefix 为 "'/usr/local'"。 返回的字符串将指向静态存储；调
   用方不应修改其值。 这对应于最高层级 "Makefile" 中的 **exec_prefix**
   变量以及在编译时传给 **configure** 脚本的 "--exec-prefix" 参数。 该
   值将以 "sys.exec_prefix" 的名称供 Python 代码使用。 它仅适用于 Unix
   。

   背景：当依赖于平台的文件（如可执行文件和共享库）是安装于不同的目录
   树中的时候 exec-prefix 将会不同于 prefix。 在典型的安装中，依赖于平
   台的文件可能安装于 the "/usr/local/plat" 子目录树而独立于平台的文件
   可能安装于 "/usr/local"。

   总而言之，平台是一组硬件和软件资源的组合，例如所有运行 Solaris 2.x
   操作系统的 Sparc 机器会被视为相同平台，但运行 Solaris 2.x 的 Intel
   机器是另一种平台，而运行 Linux 的 Intel 机器又是另一种平台。 相同操
   作系统的不同主要发布版通常也会构成不同的平台。 非 Unix 操作系统的情
   况又有所不同；这类系统上的安装策略差别巨大因此 prefix 和 exec-
   prefix 是没有意义的，并将被设为空字符串。 请注意已编译的 Python 字
   节码是独立于平台的（但并不独立于它们编译时所使用的 Python 版本！）

   系统管理员知道如何配置 **mount** 或 **automount** 程序以在平台间共
   享 "/usr/local" 而让 "/usr/local/plat" 成为针对不同平台的不同文件系
   统。

wchar_t* Py_GetProgramFullPath()

   返回 Python 可执行文件的完整程序名称；这是作为根据程序名称（由上述
   "Py_SetProgramName()" 设置）派生默认模块搜索路径的附带影响计算得出
   的。 返回的字符串将指向静态存储；调用方不应修改其值。 该值将以
   "sys.executable" 的名称供 Python 代码使用。

wchar_t* Py_GetPath()

   Return the default module search path; this is computed from the
   program name (set by "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 "':'" on Unix and Mac OS X,
   "';'" on Windows.  The returned string points into static storage;
   the caller should not modify its value.  The list "sys.path" is
   initialized with this value on interpreter startup; it can be (and
   usually is) modified later to change the search path for loading
   modules.

void Py_SetPath(const wchar_t *)

   Set the default module search path.  If this function is called
   before "Py_Initialize()", then "Py_GetPath()" won't attempt to
   compute a default search path but uses the one provided instead.
   This is useful if Python is embedded by an application that has
   full knowledge of the location of all modules.  The path components
   should be separated by the platform dependent delimiter character,
   which is "':'" on Unix and Mac OS X, "';'" on Windows.

   这也将导致 "sys.executable" 被设为程序的完整路径 (参见
   "Py_GetProgramFullPath()") 而 "sys.prefix" 和 "sys.exec_prefix" 变
   为空值。 如果在调用 "Py_Initialize()" 之后有需要则应由调用方来修改
   它们。

   Use "Py_DecodeLocale()" to decode a bytes string to get a "wchar_*"
   string.

   路径参数会在内部被复制，使调用方可以在调用结束后释放它。

   在 3.8 版更改: 现在 "sys.executable" 将使用程序的完整路径，而不是程
   序文件名。

const char* Py_GetVersion()

   返回 Python 解释器的版本。 这将为如下形式的字符串

      "3.0a5+ (py3k:63103M, May 12 2008, 00:53:55) \n[GCC 4.2.3]"

   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
   is available to Python code as "sys.version".

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 "'sunos5'".  On Mac OS X, it is "'darwin'".  On Windows, it is
   "'win'".  The returned string points into static storage; the
   caller should not modify its value.  The value is available to
   Python code as "sys.platform".

const char* Py_GetCopyright()

   返回当前 Python 版本的官方版权字符串，例如

   "'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'"

   返回的字符串指向静态存储；调用者不应修改其值。 Python 代码可通过
   "sys.copyright" 获取该值。

const char* Py_GetCompiler()

   返回用于编译当前 Python 版本的编译器指令，为带方括号的形式，例如:

      "[GCC 2.7.2.2]"

   返回的字符串指向静态存储；调用者不应修改其值。 Python 代码可以从变
   量 "sys.version" 中获取该值。

const char* Py_GetBuildInfo()

   返回有关当前Python解释器实例的序列号和构建日期和时间的信息，例如：

      "#67, Aug  1 1997, 22:34:28"

   返回的字符串指向静态存储；调用者不应修改其值。 Python 代码可以从变
   量 "sys.version" 中获取该值。

void PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)

   根据 *argc* 和 *argv* 设置 "sys.argv"。 这些形参与传给程序的
   "main()" 函数的类似，区别在于第一项应当指向要执行的脚本文件而不是
   Python 解释器对应的可执行文件。 如果没有要运行的脚本，则 *argv* 中
   的第一项可以为空字符串。 如果此函数无法初始化 "sys.argv"，则将使用
   "Py_FatalError()" 发出严重情况信号。

   如果 *updatepath* 为零，此函数将完成操作。 如果 *updatepath* 为非零
   值，则此函数还将根据以下算法修改 "sys.path":

   * 如果在 "argv[0]" 中传入一个现有脚本，则脚本所在目录的绝对路径将被
     添加到 "sys.path" 的开头。

   * 在其他情况下 (也就是说，如果 *argc* 为 "0" 或 "argv[0]" 未指向现
     有文件名)，则将在 "sys.path" 的开头添加一个空字符串，这等价于添加
     当前工作目录 (""."")。

   Use "Py_DecodeLocale()" to decode a bytes string to get a "wchar_*"
   string.

   注解:

     建议在出于执行单个脚本以外的目的嵌入 Python 解释器的应用程序传入
     "0" 作为 *updatepath*，并在需要时更新 "sys.path" 本身。 参见
     CVE-2008-5983。在 3.1.3 之前的版本中，你可以通过在调用
     "PySys_SetArgv()" 之后手动弹出第一个 "sys.path" 元素，例如使用:

        PyRun_SimpleString("import sys; sys.path.pop(0)\n");

   3.1.3 新版功能.

void PySys_SetArgv(int argc, wchar_t **argv)

   此函数相当于 "PySys_SetArgvEx()" 设置了 *updatepath* 为 "1" 除非
   **python** 解释器启动时附带了 "-I"。

   Use "Py_DecodeLocale()" to decode a bytes string to get a "wchar_*"
   string.

   在 3.4 版更改: *updatepath* 值依赖于 "-I"。

void Py_SetPythonHome(const wchar_t *home)

   设置默认的 "home" 目录，也就是标准 Python 库所在的位置。 请参阅
   "PYTHONHOME" 了解该参数字符串的含义。

   此参数应当指向静态存储中一个以零值结束的字符串，其内容在程序执行期
   间将保持不变。 Python 解释器中的代码绝不会修改此存储中的内容。

   Use "Py_DecodeLocale()" to decode a bytes string to get a "wchar_*"
   string.

w_char* Py_GetPythonHome()

   返回默认的 "home"，就是由之前对 "Py_SetPythonHome()" 的调用所设置的
   值，或者在设置了 "PYTHONHOME" 环境变量的情况下该环境变量的值。


线程状态和全局解释器锁
======================

Python 解释器不是完全线程安全的。 为了支持多线程的 Python 程序，设置了
一个全局锁，称为 *global interpreter lock* 或 *GIL*，当前线程必须在持
有它之后才能安全地访问 Python 对象。 如果没有这个锁，即使最简单的操作
也可能在多线程的程序中导致问题：例如，当两个线程同时增加相同对象的引用
计数时，引用计数可能最终只增加了一次而不是两次。

因此，规则要求只有获得 *GIL* 的线程才能在 Python对象上执行操作或调用
Python/C API 函数。 为了模拟并发执行，解释器会定期尝试切换线程 (参见
"sys.setswitchinterval()")。 锁也会在读写文件等可能造成阻塞的 I/O 操作
时释放，以便其他 Python 线程可以同时运行。

Python 解释器会在一个名为 "PyThreadState" 的数据结构体中保存一些线程专
属的记录信息。 还有一个全局变量指向当前的 "PyThreadState": 它可以使用
"PyThreadState_Get()" 来获取。


从扩展扩展代码中释放 GIL
------------------------

大多数操作 *GIL* 的扩展代码具有以下简单结构：

   Save the thread state in a local variable.
   Release the global interpreter lock.
   ... Do some blocking I/O operation ...
   Reacquire the global interpreter lock.
   Restore the thread state from the local variable.

这是如此常用因此增加了一对宏来简化它:

   Py_BEGIN_ALLOW_THREADS
   ... Do some blocking I/O operation ...
   Py_END_ALLOW_THREADS

"Py_BEGIN_ALLOW_THREADS" 宏将打开一个新块并声明一个隐藏的局部变量；
"Py_END_ALLOW_THREADS" 宏将关闭这个块。

上面的代码块可扩展为下面的代码:

   PyThreadState *_save;

   _save = PyEval_SaveThread();
   ... Do some blocking I/O operation ...
   PyEval_RestoreThread(_save);

这些函数的工作原理如下：全局解释器锁被用来保护指向当前线程状态的指针。
当释放锁并保存线程状态时，必须在锁被释放之前获取当前线程状态指针 （因
为另一个线程可以立即获取锁并将自己的线程状态存储到全局变量中）。 相应
地，当获取锁并恢复线程状态时，必须在存储线程状态指针之前先获取锁。

注解:

  调用系统 I/O 函数是释放 GIL 的最常见用例，但它在调用不需要访问
  Python 对象的长期运行计算，比如针对内存缓冲区进行操作的压缩或加密函
  数之前也很有用。 举例来说，在对数据执行压缩或哈希操作时标准 "zlib"
  和 "hashlib" 模块就会释放 GIL。


非Python创建的线程
------------------

当使用专门的 Python API（如 "threading" 模块）创建线程时，会自动关联一
个线程状态因而上面显示的代码是正确的。 但是，如果线程是用 C 创建的（例
如由具有自己的线程管理的第三方库创建），它们就不持有 GIL 也没有对应的
线程状态结构体。

如果你需要从这些线程调用 Python 代码（这通常会是上述第三方库所提供的回
调 API 的一部分），你必须首先通过创建线程状态数据结构体向解释器注册这
些线程，然后获取 GIL，最后存储它们的线程状态指针，这样你才能开始使用
Python/C API。 完成以上步骤后，你应当重置线程状态指针，释放 GIL，最后
释放线程状态数据结构体。

"PyGILState_Ensure()" 和 "PyGILState_Release()" 函数会自动完成上述的所
有操作。 从 C 线程调用到 Python 的典型方式如下:

   PyGILState_STATE gstate;
   gstate = PyGILState_Ensure();

   /* Perform Python actions here. */
   result = CallSomeFunction();
   /* evaluate result or handle exception */

   /* Release the thread. No Python API allowed beyond this point. */
   PyGILState_Release(gstate);

Note that the "PyGILState_*()" functions assume there is only one
global interpreter (created automatically by "Py_Initialize()").
Python supports the creation of additional interpreters (using
"Py_NewInterpreter()"), but mixing multiple interpreters and the
"PyGILState_*()" API is unsupported.


有关 fork() 的注意事项
----------------------

有关线程的另一个需要注意的重要问题是它们在面对 C "fork()" 调用时的行为
。 在大多数支持 "fork()" 的系统中，当一个进程执行 fork 之后将只有发出
fork 的线程存在。 这对需要如何处理锁以及CPython 的运行时内所有的存储状
态都会有实质性的影响。

The fact that only the "current" thread remains means any locks held
by other threads will never be released. Python solves this for
"os.fork()" by acquiring the locks it uses internally before the fork,
and releasing them afterwards. In addition, it resets any 锁对象 in
the child. When extending or embedding Python, there is no way to
inform Python of additional (non-Python) locks that need to be
acquired before or reset after a fork. OS facilities such as
"pthread_atfork()" would need to be used to accomplish the same thing.
Additionally, when extending or embedding Python, calling "fork()"
directly rather than through "os.fork()" (and returning to or calling
into Python) may result in a deadlock by one of Python's internal
locks being held by a thread that is defunct after the fork.
"PyOS_AfterFork_Child()" tries to reset the necessary locks, but is
not always able to.

所有其他线程都将结束这一事实也意味着 CPython 的运行时状态必须妥善清理
，"os.fork()" 就是这样做的。 这意味着最终化归属于当前解释器的所有其他
"PyThreadState" 对象以及所有其他 "PyInterpreterState" 对象。 由于这一
点以及 "main" 解释器 的特殊性质，"fork()" 应当只在该解释器 的 "main"
线程中被调用，而 CPython 全局运行时最初就是在该线程中初始化的。 只有当
"exec()" 将随后立即被调用的情况是唯一的例外。


高阶 API
--------

这些是在编写 C 扩展代码或在嵌入 Python 解释器时最常用的类型和函数：

PyInterpreterState

   该数据结构代表多个合作线程所共享的状态。 属于同一解释器的线程将共享
   其模块管理以及其他一些内部条目。 该结构体中不包含公有成员。

   最初归属于不同解释器的线程不会共享任何东西，但进程状态如可用内存、
   打开的文件描述符等等除外。 全局解释器锁也会被所有线程共享，无论它们
   归属于哪个解释器。

PyThreadState

   This data structure represents the state of a single thread.  The
   only public data member is "interp" ("PyInterpreterState *"), which
   points to this thread's interpreter state.

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
   "PyEval_ReleaseThread(tstate)". It is not needed before calling
   "PyEval_SaveThread()" or "PyEval_RestoreThread()".

   This is a no-op when called for a second time.

   在 3.7 版更改: 该函数现在由 "Py_Initialize()" 调用，因此你无需再自
   行调用它。

   在 3.2 版更改: 此函数已不再被允许在 "Py_Initialize()" 之前调用。

int PyEval_ThreadsInitialized()

   如果 "PyEval_InitThreads()" 已经被调用则返回非零值。 此函数可在不持
   有 GIL 的情况下被调用，因而可被用来避免在单线程运行时对加锁 API 的
   调用。

   在 3.7 版更改: 现在 *GIL* 将由 "Py_Initialize()" 来初始化。

PyThreadState* PyEval_SaveThread()

   释放全局解释器锁  (如果已创建) 并将线程状态重置为 "NULL"，返回之前
   的线程状态 (不为 "NULL")。 如果锁已被创建，则当前线程必须已获取到它
   。

void PyEval_RestoreThread(PyThreadState *tstate)

   获取全局解释器锁 (如果已创建) 并将线程状态设为 *tstate*，它必须不为
   "NULL"。 如果锁已被创建，则当前线程必须尚未获取它，否则将发生死锁。

   注解:

     当运行时正在最终化时从某个线程调用此函数将终结该线程，即使线程不
     是由 Python 创建的。 你可以在调用此函数之前使用
     "_Py_IsFinalizing()" 或 "sys.is_finalizing()" 来检查解释器是否还
     处于最终化过程中以避免不必要的终结。

PyThreadState* PyThreadState_Get()

   返回当前线程状态。 全局解释器锁必须被持有。 在当前状态为 "NULL" 时
   ，这将发出一个致命错误  (这样调用方将无须检查是否为 "NULL")。

PyThreadState* PyThreadState_Swap(PyThreadState *tstate)

   交换当前线程状态与由参数 *tstate* (可能为 "NULL") 给出的线程状态。
   全局解释器锁必须被持有且未被释放。

下列函数使用线程级本地存储，并且不能兼容子解释器：

PyGILState_STATE PyGILState_Ensure()

   确保当前线程已准备好调用 Python C API 而不管 Python 或全局解释器锁
   的当前状态如何。 只要每次调用都与 "PyGILState_Release()" 的调用相匹
   配就可以通过线程调用此函数任意多次。 一般来说，只要线程状态恢复到
   Release() 之前的状态就可以在 "PyGILState_Ensure()" 和
   "PyGILState_Release()" 调用之间使用其他与线程相关的 API。 例如，可
   以正常使用 "Py_BEGIN_ALLOW_THREADS" 和 "Py_END_ALLOW_THREADS" 宏。

   返回值是一个当 "PyGILState_Ensure()" 被调用时的线程状态的不透明“句
   柄”，并且必须被传递给 "PyGILState_Release()" 以确保 Python 处于相同
   状态。 虽然允许递归调用，但这些句柄 *不能* 被共享 —— 每次对
   "PyGILState_Ensure()" 的单独调用都必须保存其对
   "PyGILState_Release()" 的调用的句柄。

   当该函数返回时，当前线程将持有 GIL 并能够调用任意 Python 代码。 执
   行失败将导致致命级错误。

   注解:

     当运行时正在最终化时从某个线程调用此函数将终结该线程，即使线程不
     是由 Python 创建的。 你可以在调用此函数之前使用
     "_Py_IsFinalizing()" 或 "sys.is_finalizing()" 来检查解释器是否还
     处于最终化过程中以避免不必要的终结。

void PyGILState_Release(PyGILState_STATE)

   释放之前获取的任何资源。 在此调用之后，Python 的状态将与其在对相应
   "PyGILState_Ensure()" 调用之前的一样（但是通常此状态对调用方来说将
   是未知的，对 GILState API 的使用也是如此）。

   对 "PyGILState_Ensure()" 的每次调用都必须与在同一线程上对
   "PyGILState_Release()" 的调用相匹配。

PyThreadState* PyGILState_GetThisThreadState()

   获取此线程的当前线程状态。 如果当前线程上没有使用过 GILState API 则
   可以返回 "NULL"。 请注意主线程总是会有这样一个线程状态，即使没有在
   主线程上执行过自动线程状态调用。 这主要是一个辅助/诊断函数。

int PyGILState_Check()

   如果当前线程持有 GIL 则返回 "1" 否则返回 "0"。 此函数可以随时从任何
   线程调用。 只有当它的 Python 线程状态已经初始化并且当前持有 GIL 时
   它才会返回 "1"。 这主要是一个辅助/诊断函数。 例如在回调上下文或内存
   分配函数中会很有用处，当知道 GIL 被锁定时可以允许调用方执行敏感的操
   作或是在其他情况下做出不同的行为。

   3.4 新版功能.

以下的宏被使用时通常不带末尾分号；请在 Python 源代码发布包中查看示例用
法。

Py_BEGIN_ALLOW_THREADS

   此宏会扩展为 "{ PyThreadState *_save; _save = PyEval_SaveThread();"
   。 请注意它包含一个开头花括号；它必须与后面的
   "Py_END_ALLOW_THREADS" 宏匹配。 有关此宏的进一步讨论请参阅上文。

Py_END_ALLOW_THREADS

   此宏扩展为 "PyEval_RestoreThread(_save); }"。 注意它包含一个右花括
   号；它必须与之前的 "Py_BEGIN_ALLOW_THREADS" 宏匹配。 请参阅上文以进
   一步讨论此宏。

Py_BLOCK_THREADS

   这个宏扩展为 "PyEval_RestoreThread(_save);": 它等价于没有关闭花括号
   的 "Py_END_ALLOW_THREADS"。

Py_UNBLOCK_THREADS

   这个宏扩展为 "_save = PyEval_SaveThread();": 它等价于没有开始花括号
   和变量声明的 "Py_BEGIN_ALLOW_THREADS"。


底层级 API
----------

下列所有函数都必须在 "Py_Initialize()" 之后被调用。

在 3.7 版更改: "Py_Initialize()" 现在会初始化 *GIL*。

PyInterpreterState* PyInterpreterState_New()

   创建一个新的解释器状态对象。 不需要持有全局解释器锁，但如果有必要序
   列化对此函数的调用则可能会持有。

   引发一个不带参数的 审计事件 "cpython.PyInterpreterState_New"。

void PyInterpreterState_Clear(PyInterpreterState *interp)

   重置解释器状态对象中的所有信息。 必须持有全局解释器锁。

   引发一个不带参数的 审计事件 "cpython.PyInterpreterState_Clear"。

void PyInterpreterState_Delete(PyInterpreterState *interp)

   销毁解释器状态对象。 不需要持有全局解释器锁。 解释器状态必须使用之
   前对 "PyInterpreterState_Clear()" 的调用来重置。

PyThreadState* PyThreadState_New(PyInterpreterState *interp)

   创建属于给定解释器对象的新线程状态对象。全局解释器锁不需要保持，但
   如果需要序列化对此函数的调用，则可以保持。

void PyThreadState_Clear(PyThreadState *tstate)

   重置线程状态对象中的所有信息。 必须持有全局解释器锁。

void PyThreadState_Delete(PyThreadState *tstate)

   销毁线程状态对象。 不需要持有全局解释器锁。 线程状态必须使用之前对
   "PyThreadState_Clear()" 的调用来重置。

PY_INT64_T PyInterpreterState_GetID(PyInterpreterState *interp)

   返回解释器的唯一 ID。 如果执行过程中发生任何错误则将返回 "-1" 并设
   置错误。

   3.7 新版功能.

PyObject* PyInterpreterState_GetDict(PyInterpreterState *interp)

   返回一个存储解释器专属数据的字典。 如果此函数返回 "NULL" 则没有任何
   异常被引发并且调用方应当将解释器专属字典视为不可用。

   这不是 "PyModule_GetState()" 的替代，扩展仍应使用它来存储解释器专属
   的状态信息。

   3.8 新版功能.

PyObject* PyThreadState_GetDict()
    *Return value: Borrowed reference.*

   返回一个扩展可以在其中存储线程专属状态信息的字典。 每个扩展都应当使
   用一个独有的键用来在该字典中存储状态。 在没有可用的当前线程状态时也
   可以调用此函数。 如果此函数返回 "NULL"，则还没有任何异常被引发并且
   调用方应当假定没有可用的当前线程状态。

int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)

   Asynchronously raise an exception in a thread. The *id* argument is
   the thread id of the target thread; *exc* is the exception object
   to be raised. This function does not steal any references to *exc*.
   To prevent naive misuse, you must write your own C extension to
   call this.  Must be called with the GIL held. Returns the number of
   thread states modified; this is normally one, but will be zero if
   the thread id isn't found.  If *exc* is "NULL", the pending
   exception (if any) for the thread is cleared. This raises no
   exceptions.

   在 3.7 版更改: The type of the *id* parameter changed from "long"
   to "unsigned long".

void PyEval_AcquireThread(PyThreadState *tstate)

   Acquire the global interpreter lock and set the current thread
   state to *tstate*, which should not be "NULL".  The lock must have
   been created earlier. If this thread already has the lock, deadlock
   ensues.

   注解:

     当运行时正在最终化时从某个线程调用此函数将终结该线程，即使线程不
     是由 Python 创建的。 你可以在调用此函数之前使用
     "_Py_IsFinalizing()" 或 "sys.is_finalizing()" 来检查解释器是否还
     处于最终化过程中以避免不必要的终结。

   在 3.8 版更改: 已被更新为与 "PyEval_RestoreThread()",
   "Py_END_ALLOW_THREADS()" 和 "PyGILState_Ensure()" 保持一致，如果在
   解释器正在最终化时被调用则会终结当前线程。

   "PyEval_RestoreThread()" 是一个始终可用的（即使线程尚未初始化）更高
   层级函数。

void PyEval_ReleaseThread(PyThreadState *tstate)

   将当前线程状态重置为 "NULL" 并释放全局解释器锁。 在此之前锁必须已被
   创建并且必须由当前的线程所持有。 *tstate* 参数必须不为 "NULL"，该参
   数仅被用于检查它是否代表当前线程状态 --- 如果不是，则会报告一个致命
   级错误。

   "PyEval_SaveThread()" 是一个始终可用的（即使线程尚未初始化）更高层
   级函数。

void PyEval_AcquireLock()

   获取全局解释器锁。锁必须在此之前已被创建。 如果该线程已经拥有锁，则
   会出现死锁。

   3.2 版后已移除: 此函数不会更新当前线程状态。 请改用
   "PyEval_RestoreThread()" 或 "PyEval_AcquireThread()"。

   注解:

     当运行时正在最终化时从某个线程调用此函数将终结该线程，即使线程不
     是由 Python 创建的。 你可以在调用此函数之前使用
     "_Py_IsFinalizing()" 或 "sys.is_finalizing()" 来检查解释器是否还
     处于最终化过程中以避免不必要的终结。

   在 3.8 版更改: 已被更新为与 "PyEval_RestoreThread()",
   "Py_END_ALLOW_THREADS()" 和 "PyGILState_Ensure()" 保持一致，如果在
   解释器正在最终化时被调用则会终结当前线程。

void PyEval_ReleaseLock()

   释放全局解释器锁。 锁必须在此之前已被创建。

   3.2 版后已移除: 此函数不会更新当前线程状态。 请改用
   "PyEval_SaveThread()" 或 "PyEval_ReleaseThread()"。


子解释器支持
============

虽然在大多数用例中，你都只会嵌入一个单独的 Python 解释器，但某些场景需
要你在同一个进程甚至同一个线程中创建多个独立的解释器。 子解释器让你能
够做到这一点。

“主”解释器是在运行时初始化时创建的第一个解释器。 它通常是一个进程中唯
一的 Python 解释器。 与子解释器不同，主解释器具有唯一的进程全局责任比
如信号处理等。 它还负责在运行时初始化期间的执行并且通常还是运行时最终
化期间的活动解释器。 "PyInterpreterState_Main()" 函数将返回一个指向其
状态的指针。

你可以使用 "PyThreadState_Swap()" 函数在子解释器之间进行切换。 你可以
使用下列函数来创建和销毁它们：

PyThreadState* Py_NewInterpreter()

   新建一个子解释器。 这是一个 (几乎) 完全隔离的 Python 代码执行环境。
   特别需要注意，新的子解释器具有全部已导入模块的隔离的、独立的版本，
   包括基本模块 "builtins", "__main__" 和 "sys" 等。 已加载模块表
   ("sys.modules") 和模块搜索路径 ("sys.path") 也是隔离的。 新环境没有
   "sys.argv" 变量。 它具有新的标准 I/O 流文件对象 "sys.stdin",
   "sys.stdout" 和 "sys.stderr" (不过这些对象都指向相同的底层文件描述
   符)。

   The return value points to the first thread state created in the
   new sub-interpreter.  This thread state is made in 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.)

   扩展模块将以如下方式在（子）解释器之间共享：

   * 对于使用多阶段初始化的模块 ，例如 "PyModule_FromDefAndSpec()"，将
     为每个解释器创建并初始化一个单独的模块对象。 只有 C 层级的静态和
     全局变量能在这些模块 对象之间共享。

   * 对于使用单阶段初始化的模块，例如 "PyModule_Create()"，当特定扩展
     被首次导入时，它将被正常初始化，并会保存其模块字典的一个 (浅) 拷
     贝。 当同一扩展被另一个 (子) 解释器导入时，将初始化一个新模块并填
     充该拷贝的内容；扩展的 "init" 函数不会被调用。 因此模块字典中的对
     象最终会被 (子) 解释器所共享，这可能会导致预期之外的行为  (参见下
     文的 Bugs and caveats)。

     请注意这不同于在调用 "Py_FinalizeEx()" 和 "Py_Initialize()" 完全
     重新初始化解释器之后导入扩展时所发生的情况；对于那种情况，扩展的
     "initmodule" 函数 *会被* 再次调用。 与多阶段初始化一样，这意味着
     只有 C 层级的静态和全局变量能在这些模块之间共享。

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 interpreter are destroyed.  (The global interpreter lock
   must be held before calling this function and is still held when it
   returns.)  "Py_FinalizeEx()" will destroy all sub-interpreters that
   haven't been explicitly destroyed at that point.


错误和警告
----------

由于子解释器 (以及主解释器) 都是同一个进程的组成部分，它们之间的隔离状
态并非完美 --- 举例来说，使用低层级的文件操作如 "os.close()" 时它们可
能 (无意或恶意地) 影响它们各自打开的文件。 由于 (子) 解释器之间共享扩
展的方式，某些扩展可能无法正常工作；在使用单阶段初始化或者 (静态) 全局
变量时尤其如此。 在一个子解释器中创建的对象有可能被插入到另一个 (子)
解释器的命名空间中；这种情况应当尽可能地避免。

应当特别注意避免在子解释器之间共享用户自定义的函数、方法、实例或类，因
为由这些对象执行的导入 操作可能会影响错误的已加载模块的 (子) 解释器的
字典。 同样重要的一点是应当避免共享可被上述对象访问的对象 。

Also note that combining this functionality with "PyGILState_*()" APIs
is delicate, because these APIs assume a bijection between Python
thread states and OS-level threads, an assumption broken by the
presence of sub-interpreters. It is highly recommended that you don't
switch sub-interpreters between a pair of matching
"PyGILState_Ensure()" and "PyGILState_Release()" calls. Furthermore,
extensions (such as "ctypes") using these APIs to allow calling of
Python code from non-Python created threads will probably be broken
when using sub-interpreters.


异步通知
========

提供了一种向主解释器线程发送异步通知的机制。 这些通知将采用函数指针和
空指针参数的形式。

int Py_AddPendingCall(int (*func)(void *), void *arg)

   将一个函数加入从主解释器线程调用的计划任务。 成功时，将返回 "0" 并
   将 *func* 加入要被主线程调用的等待队列。 失败时，将返回 "-1" 但不会
   设置任何异常。

   当成功加入队列后，*func* 将 *最终* 附带参数 *arg* 被主解释器线程调
   用。 对于正常运行的 Python 代码来说它将被异步地调用，但要同时满足以
   下两个条件：

   * 位于 *bytecode* 的边界上；

   * 主线程持有 *global interpreter lock* (因此 *func* 可以使用完整的
     C API)。

   *func* 必须在成功时返回 "0"，或在失败时返回 "-1" 并设置一个异常集合
   。 *func* 不会被中断来递归地执行另一个异步通知，但如果全局解释器锁
   被释放则它仍可被中断以切换线程。

   此函数的运行不需要当前线程状态，也不需要全局解释器锁。

   警告:

     这是一个低层级函数，只在非常特殊的情况下有用。 不能保证 *func* 会
     尽快被调用。 如果主线程忙于执行某个系统调用，*func* 将不会在系统
     调用返回之前被调用。 此函数 通常 **不适合** 从任意 C 线程调用
     Python 代码。 作为替代，请使用 PyGILStateAPI。

   3.1 新版功能.


分析和跟踪
==========

Python 解释器为附加的性能分析和执行跟踪工具提供了一些低层级的支持。 它
们可被用于性能分析、调试和覆盖分析工具。

这个 C 接口允许性能分析或跟踪代码避免调用 Python 层级的可调用对象带来
的开销，它能直接执行 C 函数调用。 此工具的基本属性没有变化；这个接口允
许针对每个线程安装跟踪函数，并且向跟踪函数报告的基本事件与之前版本中向
Python 层级跟踪函数报告的事件相同。

int (*Py_tracefunc)(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg)

   The type of the trace function registered using
   "PyEval_SetProfile()" and "PyEval_SetTrace()". The first parameter
   is the object passed to the registration function as *obj*, *frame*
   is the frame object to which the event pertains, *what* is one of
   the constants "PyTrace_CALL", "PyTrace_EXCEPTION", "PyTrace_LINE",
   "PyTrace_RETURN", "PyTrace_C_CALL", "PyTrace_C_EXCEPTION",
   "PyTrace_C_RETURN", or "PyTrace_OPCODE", and *arg* depends on the
   value of *what*:

   +--------------------------------+------------------------------------------+
   | *what* 的值                    | *arg* 的含义                             |
   |================================|==========================================|
   | "PyTrace_CALL"                 | 总是 "Py_None".                          |
   +--------------------------------+------------------------------------------+
   | "PyTrace_EXCEPTION"            | "sys.exc_info()" 返回的异常信息。        |
   +--------------------------------+------------------------------------------+
   | "PyTrace_LINE"                 | 总是 "Py_None".                          |
   +--------------------------------+------------------------------------------+
   | "PyTrace_RETURN"               | 返回给调用方的值，或者如果是由异常导致的 |
   |                                | 则返回 "NULL"。                          |
   +--------------------------------+------------------------------------------+
   | "PyTrace_C_CALL"               | 正在调用函数对象。                       |
   +--------------------------------+------------------------------------------+
   | "PyTrace_C_EXCEPTION"          | 正在调用函数对象。                       |
   +--------------------------------+------------------------------------------+
   | "PyTrace_C_RETURN"             | 正在调用函数对象。                       |
   +--------------------------------+------------------------------------------+
   | "PyTrace_OPCODE"               | 总是 "Py_None".                          |
   +--------------------------------+------------------------------------------+

int PyTrace_CALL

   当对一个函数或方法的新调用被报告，或是向一个生成器增加新条目时传给
   "Py_tracefunc" 函数的 *what* 形参的值。 请注意针对生成器函数的迭代
   器的创建情况不会被报告因为在相应的帧中没有向 Python字节码转移控制权
   。

int PyTrace_EXCEPTION

   当一个异常被引发时传给 "Py_tracefunc" 函数的 *what* 形参的值。 在处
   理完任何字节码之后将附带 *what* 的值调用回调函数，在此之后该异常将
   会被设置在正在执行的帧中。 这样做的效果是当异常传播导致 Python 栈展
   开时，被调用的回调函数将随异常传播返回到每个帧。 只有跟踪函数才会接
   收到这些事件；性能分析器并不需要它们。

int PyTrace_LINE

   The value passed as the *what* parameter to a "Py_tracefunc"
   function (but not a profiling function) when a line-number event is
   being reported. It may be disabled for a frame by setting
   "f_trace_lines" to *0* on that frame.

int PyTrace_RETURN

   当一个调用即将返回时传给 "Py_tracefunc" 函数的 *what* 形参的值。

int PyTrace_C_CALL

   当一个 C 函数即将被调用时传给 "Py_tracefunc" 函数的 *what* 形参的值
   。

int PyTrace_C_EXCEPTION

   当一个 C 函数引发异常时传给 "Py_tracefunc" 函数的 *what* 形参的值。

int PyTrace_C_RETURN

   当一个 C 函数返回时传给 "Py_tracefunc" 函数的 *what* 形参的值。

int PyTrace_OPCODE

   The value for the *what* parameter to "Py_tracefunc" functions (but
   not profiling functions) when a new opcode is about to be executed.
   This event is not emitted by default: it must be explicitly
   requested by setting "f_trace_opcodes" to *1* on the frame.

void PyEval_SetProfile(Py_tracefunc func, PyObject *obj)

   Set the profiler function to *func*.  The *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 *obj* for each thread provides a
   convenient and thread-safe place to store it.  The profile function
   is called for all monitored events except "PyTrace_LINE"
   "PyTrace_OPCODE" and "PyTrace_EXCEPTION".

void PyEval_SetTrace(Py_tracefunc func, PyObject *obj)

   Set the tracing function to *func*.  This is similar to
   "PyEval_SetProfile()", except the tracing function does receive
   line-number events and per-opcode events, but does not receive any
   event related to C function objects being called.  Any trace
   function registered using "PyEval_SetTrace()" will not receive
   "PyTrace_C_CALL", "PyTrace_C_EXCEPTION" or "PyTrace_C_RETURN" as a
   value for the *what* parameter.


高级调试器支持
==============

这些函数仅供高级调试工具使用。

PyInterpreterState* PyInterpreterState_Head()

   将解释器状态对象返回到由所有此类对象组成的列表的开头。

PyInterpreterState* PyInterpreterState_Main()

   返回主解释器状态对象。

PyInterpreterState* PyInterpreterState_Next(PyInterpreterState *interp)

   从由解释器状态对象组成的列表中返回 *interp* 之后的下一项。

PyThreadState * PyInterpreterState_ThreadHead(PyInterpreterState *interp)

   在由与解释器 *interp* 相关联的线程组成的列表中返回指向第一个
   "PyThreadState" 对象的指针。

PyThreadState* PyThreadState_Next(PyThreadState *tstate)

   从由属于同一个 "PyInterpreterState" 对象的线程状态对象组成的列表中
   返回 *tstate* 之后的下一项。


线程本地存储支持
================

The Python interpreter provides low-level support for thread-local
storage (TLS) which wraps the underlying native TLS implementation to
support the Python-level thread local storage API ("threading.local").
The CPython C level APIs are similar to those offered by pthreads and
Windows: use a thread key and functions to associate a "void*" value
per thread.

当调用这些函数时 *无须* 持有 GIL；它们会提供自己的锁机制。

请注意 "Python.h" 并不包括 TLS API 的声明，你需要包括 "pythread.h" 来
使用线程本地存储。

注解:

  None of these API functions handle memory management on behalf of
  the "void*" values.  You need to allocate and deallocate them
  yourself. If the "void*" values happen to be "PyObject*", these
  functions don't do refcount operations on them either.


线程专属存储 (TSS) API
----------------------

TSS API is introduced to supersede the use of the existing TLS API
within the CPython interpreter.  This API uses a new type "Py_tss_t"
instead of "int" to represent thread keys.

3.7 新版功能.

参见: "A New C-API for Thread-Local Storage in CPython" (**PEP 539**)

Py_tss_t

   该数据结构表示线程键的状态，其定义可能依赖于下层的 TLS 实现，并且它
   有一个表示键初始化状态的内部字段。 该结构体中不存在公有成员。

   当未定义 Py_LIMITED_API 时，允许由 "Py_tss_NEEDS_INIT" 执行此类型的
   静态分配。

Py_tss_NEEDS_INIT

   这个宏将扩展为 "Py_tss_t" 变量的初始化器。 请注意这个宏不会用
   Py_LIMITED_API 来定义。


动态分配
~~~~~~~~

"Py_tss_t" 的动态分配，在使用 Py_LIMITED_API 编译的扩展模块中是必须的
，在这些模块由于此类型的实现在编译时是不透明的因此它不可能静态分配。

Py_tss_t* PyThread_tss_alloc()

   返回一个与使用 "Py_tss_NEEDS_INIT" 初始化的值的状态相同的值，或者当
   动态分配失败时则返回 "NULL"。

void PyThread_tss_free(Py_tss_t *key)

   Free the given *key* allocated by "PyThread_tss_alloc()", after
   first calling "PyThread_tss_delete()" to ensure any associated
   thread locals have been unassigned. This is a no-op if the *key*
   argument is *NULL*.

   注解:

     A freed key becomes a dangling pointer, you should reset the key
     to *NULL*.


方法
~~~~

这些函数的形参 *key* 不可为 "NULL"。 并且，如果给定的 "Py_tss_t" 还未
被 "PyThread_tss_create()" 初始化则 "PyThread_tss_set()" 和
"PyThread_tss_get()" 的行为将是未定义的。

int PyThread_tss_is_created(Py_tss_t *key)

   如果给定的 "Py_tss_t" 已通过has been initialized by
   "PyThread_tss_create()" 被初始化则返回一个非零值。

int PyThread_tss_create(Py_tss_t *key)

   当成功初始化一个 TSS 键时将返回零值。 如果 *key* 参数所指向的值未被
   "Py_tss_NEEDS_INIT" 初始化则其行为是未定义的。 此函数可在相同的键上
   重复调用 -- 在已初始化的键上调用它将不执行任何操作并立即成功返回。

void PyThread_tss_delete(Py_tss_t *key)

   销毁一个 TSS 键以便在所有线程中遗忘与该键相关联的值，并将该键的初始
   化状态改为未初始化的。 已销毁的键可以通过 "PyThread_tss_create()"
   再次被初始化。 此函数可以在同一个键上重复调用 -- 但在一个已被销毁的
   键上调用将是无效的。

int PyThread_tss_set(Py_tss_t *key, void *value)

   Return a zero value to indicate successfully associating a "void*"
   value with a TSS key in the current thread.  Each thread has a
   distinct mapping of the key to a "void*" value.

void* PyThread_tss_get(Py_tss_t *key)

   Return the "void*" value associated with a TSS key in the current
   thread.  This returns "NULL" if no value is associated with the key
   in the current thread.


线程本地存储 (TLS) API
----------------------

3.7 版后已移除: 此 API 已被 线程专属存储 (TSS) API 所取代。

注解:

  这个 API 版本不支持原生 TLS 键采用无法被安全转换为 "int" 的的定义方
  式的平台。 在这样的平台上，"PyThread_create_key()" 将立即返回一个失
  败状态，并且其他 TLS 函数在这样的平台上也都无效。

由于上面提到的兼容性问题，不应在新代码中使用此版本的API。

int PyThread_create_key()

void PyThread_delete_key(int key)

int PyThread_set_key_value(int key, void *value)

void* PyThread_get_key_value(int key)

void PyThread_delete_key_value(int key)

void PyThread_ReInitTLS()
