初始化,最终化和线程

初始化,最终化和线程

请参阅 Python 初始化配置 了解如何在初始化之前配置解释器的详情。

在Python初始化之前

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

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

备注

Despite their apparent similarity to some of the functions listed above, the following functions should not be called before the interpreter has been initialized: Py_EncodeLocale(), Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix(), Py_GetProgramFullPath(), Py_GetPythonHome(), Py_GetProgramName(), PyEval_InitThreads(), and Py_RunMain().

全局配置变量

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

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

int Py_BytesWarningFlag

此 API 仅为向下兼容而保留:应当改为设置 PyConfig.bytes_warning,参见 Python 初始化配置。

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

由 -b 选项设置。

Deprecated since version 3.12, will be removed in version 3.14.

int Py_DebugFlag

此 API 仅为向下兼容而保留:应当改为设置 PyConfig.parser_debug,参见 Python 初始化配置。

开启解析器调试输出(限专家使用,依赖于编译选项)。

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

Deprecated since version 3.12, will be removed in version 3.14.

int Py_DontWriteBytecodeFlag

此 API 仅为向下兼容而保留:应当改为设置 PyConfig.write_bytecode,参见 Python 初始化配置。

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

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

Deprecated since version 3.12, will be removed in version 3.14.

int Py_FrozenFlag

此 API 仅为向下兼容而保留:应当改为设置 PyConfig.pathconfig_warnings,参见 Python 初始化配置。

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

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

Deprecated since version 3.12, will be removed in version 3.14.

int Py_HashRandomizationFlag

此 API 仅为向下兼容而保留:应当改为设置 PyConfig.hash_seed 和 PyConfig.use_hash_seed,参见 Python 初始化配置。

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

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

Deprecated since version 3.12, will be removed in version 3.14.

int Py_IgnoreEnvironmentFlag

此 API 仅为向下兼容而保留:应当改为设置 PyConfig.use_environment,参见 Python 初始化配置。

忽略所有 PYTHON* 环境变量,例如可能设置的 PYTHONPATH 和 PYTHONHOME。

由 -E 和 -I 选项设置。

Deprecated since version 3.12, will be removed in version 3.14.

int Py_InspectFlag

此 API 被保留用于向下兼容:应当改为采用设置 PyConfig.inspect,参见 Python 初始化配置。

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

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

Deprecated since version 3.12, will be removed in version 3.14.

int Py_InteractiveFlag

此 API 被保留用于向下兼容:应当改为采用设置 PyConfig.interactive,参见 Python 初始化配置。

由 -i 选项设置。

自 3.12 版本弃用.

int Py_IsolatedFlag

此 API 被保留用于向下兼容:应当改为设置 PyConfig.isolated,参见 Python 初始化配置。

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

由 -I 选项设置。

Added in version 3.4.

Deprecated since version 3.12, will be removed in version 3.14.

int Py_LegacyWindowsFSEncodingFlag

此 API 被保留用于向下兼容:应当改为设置 PyPreConfig.legacy_windows_fs_encoding,参见 Python 初始化配置。

如果该旗标为非零值,则使用 mbcs 编码和replace 错误处理器,而不是 UTF-8 编码和 surrogatepass 错误处理器作用 filesystem encoding and error handler。

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

更多详情请参阅 PEP 529。

Availability: Windows.

Deprecated since version 3.12, will be removed in version 3.14.

int Py_LegacyWindowsStdioFlag

此 API 被保留用于向下兼容:应当改为设置 PyConfig.legacy_windows_stdio,参见 Python 初始化配置。

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

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

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

Availability: Windows.

Deprecated since version 3.12, will be removed in version 3.14.

int Py_NoSiteFlag

此 API 被保留用于向下兼容:应当改为设置 PyConfig.site_import,参见 Python 初始化配置。

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

由 -S 选项设置。

Deprecated since version 3.12, will be removed in version 3.14.

int Py_NoUserSiteDirectory

此 API 被保留用于向下兼容:应当改为设置 PyConfig.user_site_directory,参见 Python 初始化配置。

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

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

Deprecated since version 3.12, will be removed in version 3.14.

int Py_OptimizeFlag

此 API 被保留用于向下兼容:应当改为 PyConfig.optimization_level,参见 Python 初始化配置。

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

Deprecated since version 3.12, will be removed in version 3.14.

int Py_QuietFlag

此 API 被保留用于向下兼容:应当改为设置 PyConfig.quiet,参见 Python 初始化配置。

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

由 -q 选项设置。

Added in version 3.2.

Deprecated since version 3.12, will be removed in version 3.14.

int Py_UnbufferedStdioFlag

此 API 被保留用于向下兼容:应当改为设置 PyConfig.buffered_stdio,参见 Python 初始化配置。

强制 stdout 和 stderr 流不带缓冲。

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

Deprecated since version 3.12, will be removed in version 3.14.

int Py_VerboseFlag

此 API 被保留用于向下兼容:应当改为设置 PyConfig.verbose,参见 Python 初始化配置。

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

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

Deprecated since version 3.12, will be removed in version 3.14.

初始化和最终化解释器

void Py_Initialize()

属于稳定 ABI.

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

This initializes the table of loaded modules (sys.modules), and creates the fundamental modules builtins, main and sys. It also initializes the module search path (sys.path). It does not set sys.argv; use the Python Initialization Configuration API for that. This is a no-op when called for a second time (without calling Py_FinalizeEx() first). There is no return value; it is a fatal error if the initialization fails.

使用 Py_InitializeFromConfig() 来自定义 Python 初始化配置。

备注

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

void Py_InitializeEx(int initsigs)

属于稳定 ABI.

This function works like Py_Initialize() if initsigs is 1. If initsigs is 0, it skips initialization registration of signal handlers, which may be useful when CPython is embedded as part of a larger application.

使用 Py_InitializeFromConfig() 来自定义 Python 初始化配置。

PyStatus Py_InitializeFromConfig(const PyConfig *config)

Initialize Python from config configuration, as described in 使用 PyConfig 初始化.

See the Python初始化配置 section for details on pre-initializing the interpreter, populating the runtime configuration structure, and querying the returned status structure.

int Py_IsInitialized()

属于稳定 ABI.

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

int Py_IsFinalizing()

属于稳定 ABI 自 3.13 版起.

如果主 Python 解释器 正在关闭 则返回真(非零)值。 在其他情况下返回假(零)值。

Added in version 3.13.

int Py_FinalizeEx()

属于稳定 ABI 自 3.6 版起.

撤销 Py_Initialize() 所做的所有初始化和随后对 Python/C API 函数的使用,并销毁自上次调用 Py_Initialize() 以来创建但尚未销毁的所有子解释器 (见下文 Py_NewInterpreter())。 在理想情况下,这会释放 Python 解释器分配的所有内存。 当第二次调用时(在没有再次调用 Py_Initialize() 的情况下),该函数不执行任何操作。

由于这是 Py_Initialize() 的逆向操作,因而它应当在激活同一解释器的同一线程中被调用。 这意味着主线程和主解释器。 当 Py_RunMain() 仍然运行时则绝不应调用此函数。

通常返回值为 0。 如果在最终化(刷新缓冲的数据)期间发生错误,则返回 -1。

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

程序问题和注意事项: 模块和模块中对象的销毁是按随机顺序进行的;这可能导致依赖于其他对象(甚至函数)或模块的析构器(即 del() 方法)出错。 Python 所加载的动态加载扩展模块不会被卸载。 Python 解释器所分配的少量内存可能不会被释放(如果发现内存泄漏,请报告问题)。 对象间循环引用所占用的内存不会被释放。 扩展模块所分配的某些内存可能不会被释放。 如果某些扩展的初始化例程被调用多次它们可能无法正常工作;如果应用程序多次调用了 Py_Initialize() 和 Py_FinalizeEx() 就可能发生这种情况。

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

Added in version 3.6.

void Py_Finalize()

属于稳定 ABI.

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

int Py_BytesMain(int argc, char **argv)

属于稳定 ABI 自 3.8 版起.

Similar to Py_Main() but argv is an array of bytes strings, allowing the calling application to delegate the text decoding step to the CPython runtime.

Added in version 3.8.

int Py_Main(int argc, wchar_t **argv)

属于稳定 ABI.

The main program for the standard interpreter, encapsulating a full initialization/finalization cycle, as well as additional behaviour to implement reading configurations settings from the environment and command line, and then executing __main__ in accordance with 命令行.

This is made available for programs which wish to support the full CPython command line interface, rather than just embedding a Python runtime in a larger application.

The argc and argv parameters are similar to those which are passed to a C program’s main() function, except that the argv entries are first converted to wchar_t using Py_DecodeLocale(). It is also important to note that the argument list entries may be modified to point to strings other than those passed in (however, the contents of the strings pointed to by the argument list are not modified).

The return value will be 0 if the interpreter exits normally (i.e., without an exception), 1 if the interpreter exits due to an exception, or 2 if the argument list does not represent a valid Python command line.

Note that if an otherwise unhandled SystemExit is raised, this function will not return 1, but exit the process, as long as Py_InspectFlag is not set. If Py_InspectFlag is set, execution will drop into the interactive Python prompt, at which point a second otherwise unhandled SystemExit will still exit the process, while any other means of exiting will set the return value as described above.

In terms of the CPython runtime configuration APIs documented in the runtime configuration section (and without accounting for error handling), Py_Main is approximately equivalent to:

PyConfig config;
PyConfig_InitPythonConfig(&config);
PyConfig_SetArgv(&config, argc, argv);
Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);

Py_RunMain();

In normal usage, an embedding application will call this function instead of calling Py_Initialize(), Py_InitializeEx() or Py_InitializeFromConfig() directly, and all settings will be applied as described elsewhere in this documentation. If this function is instead called after a preceding runtime initialization API call, then exactly which environmental and command line configuration settings will be updated is version dependent (as it depends on which settings correctly support being modified after they have already been set once when the runtime was first initialized).

int Py_RunMain(void)

Executes the main module in a fully configured CPython runtime.

Executes the command (PyConfig.run_command), the script (PyConfig.run_filename) or the module (PyConfig.run_module) specified on the command line or in the configuration. If none of these values are set, runs the interactive Python prompt (REPL) using the __main__ module’s global namespace.

If PyConfig.inspect is not set (the default), the return value will be 0 if the interpreter exits normally (that is, without raising an exception), or 1 if the interpreter exits due to an exception. If an otherwise unhandled SystemExit is raised, the function will immediately exit the process instead of returning 1.

If PyConfig.inspect is set (such as when the -i option is used), rather than returning when the interpreter exits, execution will instead resume in an interactive Python prompt (REPL) using the __main__ module’s global namespace. If the interpreter exited with an exception, it is immediately raised in the REPL session. The function return value is then determined by the way the REPL session terminates: returning 0 if the session terminates without raising an unhandled exception, exiting immediately for an unhandled SystemExit, and returning 1 for any other unhandled exception.

This function always finalizes the Python interpreter regardless of whether it returns a value or immediately exits the process due to an unhandled SystemExit exception.

See Python Configuration for an example of a customized Python that always runs in isolated mode using Py_RunMain().

进程级参数

void Py_SetProgramName(const wchar_t *name)

属于稳定 ABI.

此 API 被保留用于向下兼容:应当改为设置 PyConfig.program_name,参见 Python 初始化配置。

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

使用 Py_DecodeLocale() 来解码字节串以得到一个 wchar_* 字符串。

自 3.11 版本弃用.

wchar_t *Py_GetProgramName()

属于稳定 ABI.

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

此函数不应在 Py_Initialize() 之前被调用,否则将返回 NULL。

在 3.10 版本发生变更: 现在如果它在 Py_Initialize() 之前被调用将返回 NULL。

Deprecated since version 3.13, will be removed in version 3.15: 改为获取 sys.executable。

wchar_t *Py_GetPrefix()

属于稳定 ABI.

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

此函数不应在 Py_Initialize() 之前被调用,否则将返回 NULL。

在 3.10 版本发生变更: 现在如果它在 Py_Initialize() 之前被调用将返回 NULL。

Deprecated since version 3.13, will be removed in version 3.15: 改为获取 sys.prefix。

wchar_t *Py_GetExecPrefix()

属于稳定 ABI.

返回针对已安装的 依赖于 平台的文件的 exec-prefix 。 这是通过基于使用 PyConfig.program_name 设置的程序名称和某些环境变量所派生的一系列复杂规则获得的;举例来说,如果程序名称为 '/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 成为针对不同平台的不同文件系统。

此函数不应在 Py_Initialize() 之前被调用,否则将返回 NULL。

在 3.10 版本发生变更: 现在如果它在 Py_Initialize() 之前被调用将返回 NULL。

Deprecated since version 3.13, will be removed in version 3.15: 改为获取 sys.exec_prefix。

wchar_t *Py_GetProgramFullPath()

属于稳定 ABI.

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

此函数不应在 Py_Initialize() 之前被调用,否则将返回 NULL。

在 3.10 版本发生变更: 现在如果它在 Py_Initialize() 之前被调用将返回 NULL。

Deprecated since version 3.13, will be removed in version 3.15: 改为获取 sys.executable。

wchar_t *Py_GetPath()

属于稳定 ABI.

返回默认模块搜索路径;这是基于程序名称(由 PyConfig.program_name 设置)和某些环境变量计算得出的。 返回的字符串由一系列以依赖于平台的分隔符分开的目录名称组成。 此分隔符在 Unix 和 macOS 上为 ':',在 Windows 上为 ';'。 返回的字符串将指向静态存储;调用方不应修改其值。 列表 sys.path 将在解释器启动时使用该值来初始化;它可以在随后被修改(并且通常都会被修改)以变更用于加载模块的搜索路径。

此函数不应在 Py_Initialize() 之前被调用,否则将返回 NULL。

在 3.10 版本发生变更: 现在如果它在 Py_Initialize() 之前被调用将返回 NULL。

Deprecated since version 3.13, will be removed in version 3.15: 改为获取 sys.path。

const char *Py_GetVersion()

属于稳定 ABI.

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

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

第一个单词(到第一个空格符为止)是当前的 Python 版本;前面的字符是以点号分隔的主要和次要版本号。 返回的字符串将指向静态存储;调用方不应修改其值。 该值将以 sys.version 的名称供 Python 代码使用。

另请参阅 Py_Version 常量。

const char *Py_GetPlatform()

属于稳定 ABI.

返回当前平台的平台标识符。 在 Unix 上,这将以操作系统的“官方”名称为基础,转换为小写形式,再加上主版本号;例如,对于 Solaris 2.x,或称 SunOS 5.x,该值将为 'sunos5'。 在 macOS 上,它将为 'darwin'。 在 Windows 上它将为 'win'。 返回的字符串指向静态存储;调用方不应修改其值。 Python 代码可通过 sys.platform 获取该值。

const char *Py_GetCopyright()

属于稳定 ABI.

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

'Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam'

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

const char *Py_GetCompiler()

属于稳定 ABI.

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

"[GCC 2.7.2.2]"

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

const char *Py_GetBuildInfo()

属于稳定 ABI.

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

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

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

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

属于稳定 ABI.

此 API 被保留用于向下兼容:应当改为设置 PyConfig.argv, PyConfig.parse_argv 和 PyConfig.safe_path,参见 Python 初始化配置。

根据 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 的开头添加一个空字符串,这等价于添加当前工作目录 (".")。

使用 Py_DecodeLocale() 来解码字节串以得到一个 wchar_* 字符串。

另请参阅 Python 初始化配置 的 PyConfig.orig_argv 和 PyConfig.argv 成员。

备注

建议在出于执行单个脚本以外的目的嵌入 Python 解释器的应用传入 0 作为 updatepath ,并在需要时更新 sys.path 本身。 参见 CVE 2008-5983。

在 3.1.3 之前的版本中,你可以通过在调用 PySys_SetArgv() 之后手动弹出第一个 sys.path 元素,例如使用:

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

Added in version 3.1.3.

自 3.11 版本弃用.

void PySys_SetArgv(int argc, wchar_t **argv)

属于稳定 ABI.

此 API 仅为向下兼容而保留:应当改为设置 PyConfig.argv 并改用 PyConfig.parse_argv,参见 Python 初始化配置。

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

使用 Py_DecodeLocale() 来解码字节串以得到一个 wchar_* 字符串。

另请参阅 Python 初始化配置 的 PyConfig.orig_argv 和 PyConfig.argv 成员。

在 3.4 版本发生变更: updatepath 值依赖于 -I。

自 3.11 版本弃用.

void Py_SetPythonHome(const wchar_t *home)

属于稳定 ABI.

此 API 被保留用于向下兼容:应当改为设置 PyConfig.home,参见 Python 初始化配置。

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

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

使用 Py_DecodeLocale() 来解码字节串以得到一个 wchar_* 字符串。

自 3.11 版本弃用.

wchar_t *Py_GetPythonHome()

属于稳定 ABI.

返回默认的 “home”,就是由 PyConfig.home 所设置的值,或者在设置了 PYTHONHOME 环境变量的情况下则为该变量的值。

此函数不应在 Py_Initialize() 之前被调用,否则将返回 NULL。

在 3.10 版本发生变更: 现在如果它在 Py_Initialize() 之前被调用将返回 NULL。

Deprecated since version 3.13, will be removed in version 3.15: 改为获取 PyConfig.home 或 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 的扩展代码具有以下简单结构:

将线程状态保存到一个局部变量中。
释放全局解释器锁。
... 执行某些阻塞式的 I/O 操作 ...
重新获取全局解释器锁。
从局部变量中恢复线程状态。

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

Py_BEGIN_ALLOW_THREADS
... 执行某些阻塞式的 I/O 操作 ...
Py_END_ALLOW_THREADS

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

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

PyThreadState *_save;

_save = PyEval_SaveThread();
... 执行某些阻塞式的 I/O 操作 ...
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();

/* 在此执行 Python 动作。 */
result = CallSomeFunction();
/* 评估结果或处理异常 */

/* 释放线程。 在此之后不再允许 Python API。 */
PyGILState_Release(gstate);

请注意 PyGILState_* 函数会假定只有一个全局解释器(由 Py_Initialize() 自动创建)。 Python 支持创建额外的解释器(使用 Py_NewInterpreter() 创建),但不支持混合使用多个解释器和 PyGILState_* API。

有关 fork() 的注意事项

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

只保留“当前”线程这一事实意味着任何由其他线程所持有的锁永远不会被释放。 Python 通过在 fork 之前获取内部使用的锁,并随后释放它们的方式为 os.fork() 解决了这个问题。 此外,它还会重置子进程中的任何 锁对象。 在扩展或嵌入 Python 时,没有办法通知 Python 在 fork 之前或之后需要获取或重置的附加(非 Python)锁。 需要使用 OS 工具例如 pthread_atfork() 来完成同样的事情。 此外,在扩展或嵌入 Python 时,直接调用 fork() 而不是通过 os.fork() (并返回到或调用至 Python 中) 调用可能会导致某个被 fork 之后失效的线程所持有的 Python 内部锁发生死锁。 PyOS_AfterFork_Child() 会尝试重置必要的锁,但并不总是能够做到。

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

高阶 API

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

type PyInterpreterState

属于受限 API (作为不透明的结构体).

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

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

type PyThreadState

属于受限 API (作为不透明的结构体).

该数据结构代表单个线程的状态。 唯一的公有数据成员为:

  • PyInterpreterState *interp

该线程的解释器状态。

void PyEval_InitThreads()

属于稳定 ABI.

不执行任何操作的已弃用函数。

在 Python 3.6 及更老的版本中,此函数会在 GIL 不存在时创建它。

在 3.9 版本发生变更: 此函数现在不执行任何操作。

在 3.7 版本发生变更: 该函数现在由 Py_Initialize() 调用,因此你无需再自行调用它。

在 3.2 版本发生变更: 此函数已不再被允许在 Py_Initialize() 之前调用。

自 3.9 版本弃用.

PyThreadState *PyEval_SaveThread()

属于稳定 ABI.

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

void PyEval_RestoreThread(PyThreadState *tstate)

属于稳定 ABI.

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

备注

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

PyThreadState *PyThreadState_Get()

属于稳定 ABI.

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

另请参阅 PyThreadState_GetUnchecked()。

PyThreadState *PyThreadState_GetUnchecked()

与 PyThreadState_Get() 类似,但如果其为 NULL 则不会杀死进程并设置致命错误。 调用方要负责检查结果是否为 NULL。

Added in version 3.13: 在 Python 3.5 到 3.12 中,此函数是私有的并且命名为 _PyThreadState_UncheckedGet()。

PyThreadState PyThreadState_Swap(PyThreadState tstate)

属于稳定 ABI.

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

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

PyGILState_STATE PyGILState_Ensure()

属于稳定 ABI.

确保当前线程已准备好调用 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)

属于稳定 ABI.

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

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

PyThreadState *PyGILState_GetThisThreadState()

属于稳定 ABI.

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

int PyGILState_Check()

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

Added in version 3.4.

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

Py_BEGIN_ALLOW_THREADS

属于稳定 ABI.

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

Py_END_ALLOW_THREADS

属于稳定 ABI.

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

Py_BLOCK_THREADS

属于稳定 ABI.

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

Py_UNBLOCK_THREADS

属于稳定 ABI.

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

(本文超出站点单文档体积上限,已按小节截断)