Python 初始化配置 — Python 文档
Python初始化配置
3.8 版中的新功能。
结构:
功能:
PyConfig_Clear()
PyConfig_InitIsolatedConfig()
PyConfig_InitPythonConfig()
PyConfig_Read()
PyConfig_SetArgv()
PyConfig_SetBytesArgv()
PyConfig_SetBytesString()
PyConfig_SetString()
PyConfig_SetWideStringList()
PyPreConfig_InitIsolatedConfig()
PyPreConfig_InitPythonConfig()
PyStatus_Error()
PyStatus_Exception()
PyStatus_Exit()
PyStatus_IsError()
PyStatus_IsExit()
PyStatus_NoMemory()
PyStatus_Ok()
PyWideStringList_Append()
PyWideStringList_Insert()
Py_ExitStatusException()
Py_InitializeFromConfig()
Py_PreInitialize()
Py_PreInitializeFromArgs()
Py_PreInitializeFromBytesArgs()
Py_RunMain()
预配置(PyPreConfig
类型)存储在 _PyRuntime.preconfig
中,配置(PyConfig
类型)存储在 PyInterpreterState.config
中。
另请参见 初始化、终结和线程 。
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
列出项目。
- PyStatus PyWideStringList_Append(PyWideStringList *list, const wchar_t *item)
状态
- 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)
非零时才必须调用。
- int exitcode
笔记
在内部,Python 使用设置 PyStatus.func
的宏,而函数创建状态集 func
到 NULL
。
例子:
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_PYMALLOC
和PYMEM_ALLOCATOR_PYMALLOC_DEBUG
请参阅 内存管理 。
- int configure_locale
将 LC_CTYPE 语言环境设置为用户首选语言环境? 如果等于 0,则将 coerce_c_locale 和 coerce_c_locale_warn 设置为 0。
- int coerce_c_locale
如果等于2,则强制C语言环境; 如果等于 1,则读取 LC_CTYPE 语言环境以决定是否应该对其进行强制。
- int coerce_c_locale_warn
如果非零,则在强制 C 语言环境时发出警告。
- int dev_mode
- int 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
- 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 的大多数参数的结构。
结构方法:
- 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 设置为 length 和 items。
如果需要,预初始化 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
- wchar_t *base_executable
sys._base_executable
:__PYVENV_LAUNCHER__
环境变量值,或 PyConfig.executable 的副本。
- wchar_t *base_prefix
- int buffered_stdio
如果等于 0,则启用无缓冲模式,使 stdout 和 stderr 流无缓冲。
stdin 始终以缓冲模式打开。
- int bytes_warning
如果等于 1,则在比较 bytes 或 bytearray 与 str,或比较 bytes 与 int 时发出警告]。 如果等于或大于 2,则引发 BytesWarning 异常。
- wchar_t *check_hash_pycs_mode
控制基于哈希的
.pyc
文件的验证行为(参见 PEP 552):--check-hash-based-pycs 命令行选项值。有效值:
always
、never
和default
。默认值为:
default
。
- int configure_c_stdio
如果非零,则配置 C 标准流(
stdio
、stdout
、stdout
)。 例如,在 Windows 上将它们的模式设置为O_BINARY
。
- int dev_mode
开发模式:见-X dev。
- int dump_refs
如果非零,则转储退出时仍处于活动状态的所有对象。
需要 Python 的调试版本(必须定义
Py_REF_DEBUG
宏)。
- wchar_t *exec_prefix
- wchar_t *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_environment 和 user_site_directory 设置为 0。
- int legacy_windows_stdio
如果非零,对于 sys.stdin、sys.stdout 和 sys.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 parser_debug
如果非零,则打开解析器调试输出(仅限专家,取决于编译选项)。
- int pathconfig_warnings
如果等于 0,则在计算 Path Configuration 时禁止警告(仅限 Unix,Windows 不记录任何警告)。 否则,警告将写入
stderr
。
- wchar_t *prefix
- wchar_t *program_name
程序名称。 用于初始化 可执行文件 ,并用于早期错误消息。
- wchar_t *pycache_prefix
sys.pycache_prefix:
.pyc
缓存前缀。如果
NULL
,sys.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_alloc_count
在退出时显示分配计数?
通过 -X showalloccount 命令行选项设置为 1。
需要定义了
COUNT_ALLOCS
宏的特殊 Python 构建。
- 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.stdin、sys.stdout和sys.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
- PyStatus PyConfig_SetString(PyConfig *config, wchar_t *const *config_str, const wchar_t *str)
如果 parse_argv
非零,argv
参数的解析方式与常规 Python 解析命令行参数的方式相同,并且 Python 参数从 argv
中剥离:参见 Command行参数。
解析 xoptions
选项以设置其他选项:参见 -X 选项。
使用 PyConfig 初始化
初始化 Python 的函数:
- 从 config 配置初始化 Python。
调用者负责使用 PyStatus_Exception()
和 Py_ExitStatusException()
处理异常(错误或退出)。
如果使用 PyImport_FrozenModules
、PyImport_AppendInittab()
或 PyImport_ExtendInittab()
,则必须在 Python 预初始化之后和 Python 初始化之前设置或调用它们。
设置程序名称示例:
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]PYTHONUTF8 和 PYTHONCOERCECLOCALE 环境变量。
始终以隔离模式运行的自定义 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 包含多个用于路径配置的字段:
- 路径配置输入:
PyConfig.home
PyConfig.pathconfig_warnings
PyConfig.program_name
PyConfig.pythonpath_env
- 当前工作目录:获取绝对路径
PATH
环境变量获取程序完整路径(来自 PyConfig.program_name)__PYVENV_LAUNCHER__
环境变量- (仅限 Windows)注册表中 HKEY_CURRENT_USER 和 HKEY_LOCAL_MACHINE(其中 XY 是 Python 版本)的“SoftwarePythonPythonCoreX.YPythonPath”下的应用程序路径。
- 路径配置输出字段:
如果至少有一个“输出字段”未设置,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_prefix 或 base_exec_prefix 字段,则它们分别从 prefix 和 exec_prefix 继承其值。
Py_RunMain() 和 Py_Main() 修改 sys.path:
- 如果设置了 run_filename 并且是包含
__main__.py
脚本的目录,则将 run_filename 添加到 sys.path。 - 如果 isolated 为零:
- 如果设置了 run_module,则将当前目录添加到 sys.path。 如果无法读取当前目录,则不执行任何操作。
- 如果设置了 run_filename,则将文件名的目录添加到 sys.path。
- 否则,在 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 配置 。
多阶段初始化私有临时 API
本节是介绍多阶段初始化的私有临时API,PEP 432的核心特性:
- “核心”初始化阶段,“最低限度的 Python”:
- “Main”初始化阶段,Python完全初始化:
- 安装配置importlib;
- 应用路径配置;
- 安装信号处理程序;
- 完成 sys 模块初始化(例如:创建 sys.stdout 和 sys.path);
- 启用可选功能,如 faulthandler 和 tracemalloc;
- 导入site模块;
- 等等。
私有临时 API:
PyConfig._init_main
:如果设置为 0,则 Py_InitializeFromConfig() 在“Core”初始化阶段停止。
- 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);
}
}