Python 初始化配置 — Python 文档

来自菜鸟教程
Python/docs/3.9/c-api/init config
跳转至:导航、​搜索

Python初始化配置

3.8 版中的新功能。


结构:

功能:

预配置(PyPreConfig 类型)存储在 _PyRuntime.preconfig 中,配置(PyConfig 类型)存储在 PyInterpreterState.config 中。

另请参见 初始化、终结和线程

也可以看看

PEP 587“Python 初始化配置”。


PyWideStringList

type PyWideStringList

wchar_t* 字符串列表。

如果 length 非零,则 items 必须是非 NULL 并且所有字符串都必须是非 NULL

方法:

PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)

item 附加到 list

必须预先初始化 Python 才能调用此函数。

PyStatus PyWideStringList_Insert(PyWideStringList *list, Py_ssize_t index, const wchar_t *item)

项目 插入 列表索引

如果 index 大于或等于 list 长度,则将 item 附加到 list

index 必须大于或等于 0。

必须预先初始化 Python 才能调用此函数。

结构字段:

Py_ssize_t length

列表长度。

wchar_t **items

列出项目。


状态

type PyStatus

存储初始化函数状态的结构:成功、错误或退出。

对于错误,它可以存储创建错误的 C 函数名称。

结构字段:

int exitcode

退出代码。 参数传递给 exit()

const char *err_msg

错误信息。

const char *func

产生错误的函数名,可以是NULL

创建状态的函数:

PyStatus PyStatus_Ok(void)

成功。

PyStatus PyStatus_Error(const char *err_msg)

带有消息的初始化错误。

PyStatus PyStatus_NoMemory(void)

内存分配失败(内存不足)。

PyStatus PyStatus_Exit(int exitcode)

使用指定的退出代码退出 Python。

处理状态的函数:

int PyStatus_Exception(PyStatus status)

状态是错误还是退出? 如果为真,则必须处理异常; 例如,通过调用 Py_ExitStatusException()

int PyStatus_IsError(PyStatus status)

结果是错误吗?

int PyStatus_IsExit(PyStatus status)

结果是退出吗?

void Py_ExitStatusException(PyStatus status)

如果 status 是退出,则调用 exit(exitcode)。 如果 status 是错误,则打印错误消息并以非零退出代码退出。 仅当 PyStatus_Exception(status) 非零时才必须调用。

笔记

在内部,Python 使用设置 PyStatus.func 的宏,而函数创建状态集 funcNULL


例子:

PyStatus alloc(void **ptr, size_t size)
{
    *ptr = PyMem_RawMalloc(size);
    if (*ptr == NULL) {
        return PyStatus_NoMemory();
    }
    return PyStatus_Ok();
}

int main(int argc, char **argv)
{
    void *ptr;
    PyStatus status = alloc(&ptr, 16);
    if (PyStatus_Exception(status)) {
        Py_ExitStatusException(status);
    }
    PyMem_Free(ptr);
    return 0;
}

预配置

type PyPreConfig

用于预初始化 Python 的结构:

  • 设置 Python 内存分配器

  • 配置 LC_CTYPE 语言环境

  • 设置 UTF-8 模式

初始化预配置的函数:

void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig)

使用 Python Configuration 初始化预配置。

void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig)

使用 隔离配置 初始化预配置。

结构字段:

int allocator

内存分配器的名称:

  • PYMEM_ALLOCATOR_NOT_SET (0):不改变内存分配器(使用默认值)

  • PYMEM_ALLOCATOR_DEFAULT (1):默认内存分配器

  • PYMEM_ALLOCATOR_DEBUG (2):带有调试钩子的默认内存分配器

  • PYMEM_ALLOCATOR_MALLOC (3):强制使用malloc()

  • PYMEM_ALLOCATOR_MALLOC_DEBUG (4):强制使用带有调试钩子的 malloc()

  • PYMEM_ALLOCATOR_PYMALLOC (5): Python pymalloc 内存分配器

  • PYMEM_ALLOCATOR_PYMALLOC_DEBUG (6):Python pymalloc 内存分配器 带调试钩子

如果使用 --without-pymalloc 配置 Python,则不支持 PYMEM_ALLOCATOR_PYMALLOCPYMEM_ALLOCATOR_PYMALLOC_DEBUG

请参阅 内存管理

int configure_locale

将 LC_CTYPE 语言环境设置为用户首选语言环境? 如果等于 0,则将 coerce_c_localecoerce_c_locale_warn 设置为 0。

int coerce_c_locale

如果等于2,则强制C语言环境; 如果等于 1,则读取 LC_CTYPE 语言环境以决定是否应该对其进行强制。

int coerce_c_locale_warn

如果非零,则在强制 C 语言环境时发出警告。

int dev_mode

参见 PyConfig.dev_mode

int isolated

参见 PyConfig.isolated

int legacy_windows_fs_encoding(Windows only)

如果非零,则禁用 UTF-8 模式,将 Python 文件系统编码设置为 mbcs,将文件系统错误处理程序设置为 replace

仅在 Windows 上可用。 #ifdef MS_WINDOWS 宏可用于 Windows 特定代码。

int parse_argv

如果非零,Py_PreInitializeFromArgs()Py_PreInitializeFromBytesArgs() 解析它们的 argv 参数与常规 Python 解析命令行参数的方式相同:参见 Command Line参数

int use_environment

参见 PyConfig.use_environment

int utf8_mode

如果非零,则启用 UTF-8 模式。


使用 PyPreConfig 进行预初始化

用于预初始化 Python 的函数:

PyStatus Py_PreInitialize(const PyPreConfig *preconfig)
preconfig 预配置预初始化 Python。
PyStatus Py_PreInitializeFromBytesArgs(const PyPreConfig *preconfig, int argc, char *const *argv)
preconfig 预配置和命令行参数(字节字符串)预初始化 Python。
PyStatus Py_PreInitializeFromArgs(const PyPreConfig *preconfig, int argc, wchar_t *const *argv)
preconfig 预配置和命令行参数(宽字符串)预初始化 Python。

调用者负责使用 PyStatus_Exception()Py_ExitStatusException() 处理异常(错误或退出)。

对于 Python 配置 (PyPreConfig_InitPythonConfig()),如果使用命令行参数初始化 Python,则还必须传递命令行参数来预初始化 Python,因为它们对预配置有影响,例如编码。 例如,-X utf8 命令行选项启用 UTF-8 模式。

PyMem_SetAllocator() 可以在 Py_PreInitialize() 之后和 Py_InitializeFromConfig() 之前调用以安装自定义内存分配器。 如果 PyPreConfig.allocator 设置为 PYMEM_ALLOCATOR_NOT_SET,则可以在 Py_PreInitialize() 之前调用它。

Python 内存分配函数如 PyMem_RawMalloc() 不得在 Python 预初始化之前使用,而直接调用 malloc()free() 总是安全的。 Py_DecodeLocale() 在预初始化之前不能被调用。

使用预初始化启用 UTF-8 模式的示例:

PyStatus status;
PyPreConfig preconfig;
PyPreConfig_InitPythonConfig(&preconfig);

preconfig.utf8_mode = 1;

status = Py_PreInitialize(&preconfig);
if (PyStatus_Exception(status)) {
    Py_ExitStatusException(status);
}

/* at this point, Python will speak UTF-8 */

Py_Initialize();
/* ... use Python API here ... */
Py_Finalize();

配置文件

type PyConfig

包含用于配置 Python 的大多数参数的结构。

结构方法:

void PyConfig_InitPythonConfig(PyConfig *config)

使用 Python 配置 初始化配置。

void PyConfig_InitIsolatedConfig(PyConfig *config)

使用 隔离配置 初始化配置。

PyStatus PyConfig_SetString(PyConfig *config, wchar_t *const *config_str, const wchar_t *str)

将宽字符串str复制到*config_str中。

如果需要,预初始化 Python。

PyStatus PyConfig_SetBytesString(PyConfig *config, wchar_t *const *config_str, const char *str)

使用 Py_DecodeLocale() 解码 str 并将结果设置为 *config_str

如果需要,预初始化 Python。

PyStatus PyConfig_SetArgv(PyConfig *config, int argc, wchar_t *const *argv)

从宽字符串设置命令行参数。

如果需要,预初始化 Python。

PyStatus PyConfig_SetBytesArgv(PyConfig *config, int argc, char *const *argv)

设置命令行参数:使用 Py_DecodeLocale() 解码字节。

如果需要,预初始化 Python。

PyStatus PyConfig_SetWideStringList(PyConfig *config, PyWideStringList *list, Py_ssize_t length, wchar_t **items)

将宽字符串列表 list 设置为 lengthitems

如果需要,预初始化 Python。

PyStatus PyConfig_Read(PyConfig *config)

阅读所有 Python 配置。

已经初始化的字段保持不变。

如果需要,预初始化 Python。

void PyConfig_Clear(PyConfig *config)

释放配置内存。

如果需要,大多数 PyConfig 方法会预初始化 Python。 在这种情况下,Python 预初始化配置基于 PyConfig。 如果调整了与 PyPreConfig 共同的配置字段,则必须在调用 PyConfig 方法之前设置它们:

此外,如果使用 PyConfig_SetArgv()PyConfig_SetBytesArgv(),则必须先调用此方法,然后再调用其他方法,因为预初始化配置取决于命令行参数(如果 parse_argv 非零)。

这些方法的调用者负责使用 PyStatus_Exception()Py_ExitStatusException() 处理异常(错误或退出)。

结构字段:

PyWideStringList argv

命令行参数,sys.argv。 请参阅 parse_argv 以与常规 Python 解析 Python 命令行参数相同的方式解析 argv。 如果 argv 为空,则添加一个空字符串以确保 sys.argv 始终存在且永不为空。

wchar_t *base_exec_prefix

sys.base_exec_prefix

wchar_t *base_executable

sys._base_executable__PYVENV_LAUNCHER__ 环境变量值,或 PyConfig.executable 的副本。

wchar_t *base_prefix

sys.base_prefix

wchar_t *platlibdir

sys.platlibdir:平台库目录名,配置时由--with-platlibdir设置,可被PYTHONPLATLIBDIR环境变量覆盖。

3.9 版中的新功能。

int buffered_stdio

如果等于 0,则启用无缓冲模式,使 stdout 和 stderr 流无缓冲。

stdin 始终以缓冲模式打开。

int bytes_warning

如果等于 1,则在比较 bytesbytearraystr,或比较 bytesint 时发出警告]。 如果等于或大于 2,则引发 BytesWarning 异常。

wchar_t *check_hash_pycs_mode

控制基于哈希的 .pyc 文件的验证行为(参见 PEP 552):--check-hash-based-pycs 命令行选项值。

有效值:alwaysneverdefault

默认值为:default

int configure_c_stdio

如果非零,则配置 C 标准流(stdiostdoutstdout)。 例如,在 Windows 上将它们的模式设置为 O_BINARY

int dev_mode

如果非零,则启用 Python 开发模式

int dump_refs

如果非零,则转储退出时仍处于活动状态的所有对象。

Py_TRACE_REFS 宏必须在构建中定义。

wchar_t *exec_prefix

sys.exec_prefix

wchar_t *executable

sys.executable

int faulthandler

如果非零,则在启动时调用 faulthandler.enable()

wchar_t *filesystem_encoding

文件系统编码,sys.getfilesystemencoding()

wchar_t *filesystem_errors

文件系统编码错误,sys.getfilesystemencodeerrors()

unsigned long hash_seed
int use_hash_seed

随机散列函数种子。

如果 use_hash_seed 为零,则在 Pythonstartup 时随机选择一个种子,并忽略 hash_seed

wchar_t *home

Python 主目录。

默认从 PYTHONHOME 环境变量值初始化。

int import_time

如果非零,则配置文件导入时间。

int inspect

执行脚本或命令后进入交互模式。

int install_signal_handlers

安装信号处理程序?

int interactive

交互模式。

int isolated

如果大于 0,则启用隔离模式:

  • sys.path 既不包含脚本目录(从 argv[0] 或当前目录计算)也不包含用户的站点包目录。

  • Python REPL 不会导入 readline,也不会在交互式提示中启用默认的 readline 配置。

  • use_environmentuser_site_directory 设置为 0。

int legacy_windows_stdio

如果非零,对于 sys.stdinsys.stdoutsys.stderr,使用 io.FileIO 而不是 io.WindowsConsoleIO

仅在 Windows 上可用。 #ifdef MS_WINDOWS 宏可用于 Windows 特定代码。

int malloc_stats

如果非零,则在退出时转储 Python pymalloc 内存分配器 的统计信息。

如果 Python 是使用 --without-pymalloc 构建的,则该选项将被忽略。

wchar_t *pythonpath_env

模块搜索路径为由 DELIM (os.path.pathsep) 分隔的字符串。

默认从 PYTHONPATH 环境变量值初始化。

PyWideStringList module_search_paths
int module_search_paths_set

sys.path。 如果 module_search_paths_set 等于 0,module_search_paths 被计算 Path Configuration 的函数覆盖。

int optimization_level

编译优化级别:

  • 0:窥孔优化器(并将__debug__设置为True

  • 1:移除断言,将__debug__设置为False

  • 2:剥离文档字符串

int parse_argv

如果非零,则以与常规 Python 命令行参数相同的方式解析 argv,并从 argv 中去除 Python 参数:请参阅 命令行参数

int parser_debug

如果非零,则打开解析器调试输出(仅限专家,取决于编译选项)。

int pathconfig_warnings

如果等于 0,则在计算 Path Configuration 时禁止警告(仅限 Unix,Windows 不记录任何警告)。 否则,警告将写入 stderr

wchar_t *prefix

sys.prefix

wchar_t *program_name

程序名称。 用于初始化 可执行文件 ,并用于早期错误消息。

wchar_t *pycache_prefix

sys.pycache_prefix.pyc 缓存前缀。

如果NULLsys.pycache_prefix设置为None

int quiet

静音模式。 例如,不要在交互模式下显示版权和版本消息。

wchar_t *run_command

python3 -c COMMAND 参数。 由 Py_RunMain() 使用。

wchar_t *run_filename

python3 FILENAME 参数。 由 Py_RunMain() 使用。

wchar_t *run_module

python3 -m MODULE 参数。 由 Py_RunMain() 使用。

int show_ref_count

在退出时显示总引用计数?

通过 -X showrefcount 命令行选项设置为 1。

需要 Python 的调试版本(必须定义 Py_REF_DEBUG 宏)。

int site_import

启动时导入site模块?

int skip_source_first_line

跳过源代码的第一行?

wchar_t *stdio_encoding
wchar_t *stdio_errors

sys.stdinsys.stdoutsys.stderr的编码和编码错误。

int tracemalloc

如果非零,则在启动时调用 tracemalloc.start()

int use_environment

如果大于 0,则使用 环境变量

int user_site_directory

如果非零,则将用户站点目录添加到 sys.path

int verbose

如果非零,则启用详细模式。

PyWideStringList warnoptions

sys.warnoptions:用于构建警告过滤器的 warnings 模块的选项:从最低到最高优先级。

warnings模块以相反的顺序添加了sys.warnoptions:最后一个PyConfig.warnoptions项成为warnings.filters的第一个被勾选的项第一(最高优先级)。

int write_bytecode

如果非零,则写入 .pyc 文件。

sys.dont_write_bytecode 被初始化为 write_bytecode 的反转值。

PyWideStringList xoptions

sys._xoptions

int _use_peg_parser

启用 PEG 解析器? 默认值:1。

-X oldparserPYTHONOLDPARSER 设置为 0。

另见 PEP 617

如果 parse_argv 非零,argv 参数的解析方式与常规 Python 解析命令行参数的方式相同,并且 Python 参数从 argv 中剥离:参见 Command行参数

解析 xoptions 选项以设置其他选项:参见 -X 选项。

3.9 版更改: show_alloc_count 字段已删除。


使用 PyConfig 初始化

初始化 Python 的函数:

PyStatus Py_InitializeFromConfig(const PyConfig *config)
config 配置初始化 Python。

调用者负责使用 PyStatus_Exception()Py_ExitStatusException() 处理异常(错误或退出)。

如果使用 PyImport_FrozenModules()PyImport_AppendInittab()PyImport_ExtendInittab(),则必须在 Python 初始化之后和 Python 初始化之前设置或调用它们。 如果 Python 被多次初始化,则必须在每次 Python 初始化之前调用 PyImport_AppendInittab()PyImport_ExtendInittab()

设置程序名称示例:

void init_python(void)
{
    PyStatus status;

    PyConfig config;
    PyConfig_InitPythonConfig(&config);

    /* Set the program name. Implicitly preinitialize Python. */
    status = PyConfig_SetString(&config, &config.program_name,
                                L"/path/to/my_program");
    if (PyStatus_Exception(status)) {
        goto fail;
    }

    status = Py_InitializeFromConfig(&config);
    if (PyStatus_Exception(status)) {
        goto fail;
    }
    PyConfig_Clear(&config);
    return;

fail:
    PyConfig_Clear(&config);
    Py_ExitStatusException(status);
}

更完整的例子修改默认配置,读取配置,然后覆盖一些参数:

PyStatus init_python(const char *program_name)
{
    PyStatus status;

    PyConfig config;
    PyConfig_InitPythonConfig(&config);

    /* Set the program name before reading the configuration
       (decode byte string from the locale encoding).

       Implicitly preinitialize Python. */
    status = PyConfig_SetBytesString(&config, &config.program_name,
                                  program_name);
    if (PyStatus_Exception(status)) {
        goto done;
    }

    /* Read all configuration at once */
    status = PyConfig_Read(&config);
    if (PyStatus_Exception(status)) {
        goto done;
    }

    /* Append our custom search path to sys.path */
    status = PyWideStringList_Append(&config.module_search_paths,
                                     L"/path/to/more/modules");
    if (PyStatus_Exception(status)) {
        goto done;
    }

    /* Override executable computed by PyConfig_Read() */
    status = PyConfig_SetString(&config, &config.executable,
                                L"/path/to/my_executable");
    if (PyStatus_Exception(status)) {
        goto done;
    }

    status = Py_InitializeFromConfig(&config);

done:
    PyConfig_Clear(&config);
    return status;
}

隔离配置

PyPreConfig_InitIsolatedConfig()PyConfig_InitIsolatedConfig() 函数创建一个配置以将 Python 与系统隔离。 例如,将 Python 嵌入到应用程序中。

此配置忽略全局配置变量、环境变量、命令行参数(PyConfig.argv 未解析)和用户站点目录。 C 标准流(例如:stdout)和 LC_CTYPE 语言环境保持不变。 未安装信号处理程序。

配置文件仍然与此配置一起使用。 设置Path Configuration(“输出字段”)忽略这些配置文件,避免函数计算默认路径配置。


Python 配置

PyPreConfig_InitPythonConfig()PyConfig_InitPythonConfig() 函数创建一个配置来构建一个自定义的 Python,它的行为与常规 Python 相同。

环境变量和命令行参数用于配置 Python,而忽略全局配置变量。

此函数根据 LC_CTYPE 语言环境启用 C 语言环境强制(PEP 538)和 UTF-8 模式(PEP 540),[ X145X]PYTHONUTF8PYTHONCOERCECLOCALE 环境变量。

始终以隔离模式运行的自定义 Python 示例:

int main(int argc, char **argv)
{
    PyStatus status;

    PyConfig config;
    PyConfig_InitPythonConfig(&config);
    config.isolated = 1;

    /* Decode command line arguments.
       Implicitly preinitialize Python (in isolated mode). */
    status = PyConfig_SetBytesArgv(&config, argc, argv);
    if (PyStatus_Exception(status)) {
        goto fail;
    }

    status = Py_InitializeFromConfig(&config);
    if (PyStatus_Exception(status)) {
        goto fail;
    }
    PyConfig_Clear(&config);

    return Py_RunMain();

fail:
    PyConfig_Clear(&config);
    if (PyStatus_IsExit(status)) {
        return status.exitcode;
    }
    /* Display the error message and exit the process with
       non-zero exit code */
    Py_ExitStatusException(status);
}

路径配置

PyConfig 包含多个用于路径配置的字段:

如果至少有一个“输出字段”未设置,Python 会计算路径配置以填充未设置的字段。 如果 module_search_paths_set 等于 0,则 module_search_paths 被覆盖并且 module_search_paths_set 设置为 1。

通过明确设置上面列出的所有路径配置输出字段,可以完全忽略计算默认路径配置的函数。 一个字符串即使是非空的也被视为已设置。 如果 module_search_paths_set 设置为 1,则认为 module_search_paths 已设置。 在这种情况下,路径配置输入字段也会被忽略。

pathconfig_warnings 设置为 0 以在计算路径配置时抑制警告(仅限 Unix,Windows 不记录任何警告)。

如果未设置 base_prefixbase_exec_prefix 字段,则它们分别从 prefixexec_prefix 继承其值。

Py_RunMain()Py_Main() 修改 sys.path

如果 site_import 非零,sys.path 可以被 site 模块修改。 如果 user_site_directory 非零且用户的站点包目录存在,则 site 模块将用户的站点包目录附加到 sys.path

路径配置使用以下配置文件:

  • pyvenv.cfg
  • python._pth(仅限 Windows)
  • pybuilddir.txt(仅限 Unix)

__PYVENV_LAUNCHER__环境变量用于设置PyConfig.base_executable


Py_RunMain()

int Py_RunMain(void)

执行在命令行或在配置。

默认情况下,如果使用 -i 选项,则运行 REPL。

最后,完成 Python 并返回可以传递给 exit() 函数的退出状态。

有关使用 Py_RunMain() 始终在隔离模式下运行的自定义 Python 的示例,请参阅 Python 配置


Py_GetArgcArgv()

void Py_GetArgcArgv(int *argc, wchar_t ***argv)
在 Python 修改它们之前获取原始命令行参数。


多阶段初始化私有临时 API

本节是介绍多阶段初始化的私有临时API,PEP 432的核心特性:

  • “核心”初始化阶段,“最低限度的 Python”:
    • 内置类型;
    • 内置异常;
    • 内置和冻结模块;
    • sys 模块仅部分初始化(例如:sys.path 尚不存在)。
  • “Main”初始化阶段,Python完全初始化:

私有临时 API:

  • PyConfig._init_main:如果设置为 0,则 Py_InitializeFromConfig() 在“Core”初始化阶段停止。
  • PyConfig._isolated_interpreter:如果非零,则禁止线程、子进程和分叉。
PyStatus _Py_InitializeMain(void)
进入“Main”初始化阶段,完成Python初始化。

在“Core”阶段没有导入模块,并且没有配置importlib模块:Path Configuration仅在“Main”阶段应用。 它可能允许在 Python 中自定义 Python 以覆盖或调整 路径配置 ,可能安装自定义 sys.meta_path 导入器或导入钩子等。

在核心阶段之后和主阶段之前,可以在 Python 中计算 路径配置 ,这是 PEP 432 的动机之一。

“核心”阶段没有正确定义:在这个阶段什么应该可用,什么不应该可用还没有指定。 API 被标记为私有和临时:在设计出合适的公共 API 之前,可以随时修改甚至删除 API。

在“Core”和“Main”初始化阶段之间运行 Python 代码的示例:

void init_python(void)
{
    PyStatus status;

    PyConfig config;
    PyConfig_InitPythonConfig(&config);
    config._init_main = 0;

    /* ... customize 'config' configuration ... */

    status = Py_InitializeFromConfig(&config);
    PyConfig_Clear(&config);
    if (PyStatus_Exception(status)) {
        Py_ExitStatusException(status);
    }

    /* Use sys.stderr because sys.stdout is only created
       by _Py_InitializeMain() */
    int res = PyRun_SimpleString(
        "import sys; "
        "print('Run Python code before _Py_InitializeMain', "
               "file=sys.stderr)");
    if (res < 0) {
        exit(1);
    }

    /* ... put more configuration code here ... */

    status = _Py_InitializeMain();
    if (PyStatus_Exception(status)) {
        Py_ExitStatusException(status);
    }
}