如何设置Python可执行文件名,因Py_SetProgramName()已弃用?
Python 3.12的嵌入文档提供了一个示例:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
Py_SetProgramName(program); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print('Today is', ctime(time()))\n");
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
return 0;
}
虽然建议调用 Py_SetProgramName()
,但这会产生一个编译警告:
test01.c:12:5: warning: 'Py_SetProgramName' is deprecated [-Wdeprecated-declarations]
Py_SetProgramName(program); /* optional but recommended */
^
/opt/python/3.11/include/python3.11/pylifecycle.h:37:1: note: 'Py_SetProgramName' has been explicitly marked deprecated here
Py_DEPRECATED(3.11) PyAPI_FUNC(void) Py_SetProgramName(const wchar_t *);
^
/opt/python/3.11/include/python3.11/pyport.h:336:54: note: expanded from macro 'Py_DEPRECATED'
#define Py_DEPRECATED(VERSION_UNUSED) __attribute__((__deprecated__))
^
1 warning generated.
生成的可执行文件可以运行,如果你在 PyRun_SimpleString()
的参数中添加 import sys
和 print(sys.executable)
,就会显示正确的可执行文件名称。
由于在3.11版本中这个方法已经被弃用,虽然在3.12中仍然推荐使用,但我想去掉这个警告。我该如何修改程序呢?
1 个回答
0
根据文档中提到的关于 Py_SetProgramName
的替代方案,并成功合并了来自 使用 PyConfig 初始化 的代码,我写出了这个可以运行的程序:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
wchar_t *program = Py_DecodeLocale(argv[0], NULL);
if (program == NULL) {
fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
exit(1);
}
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
status = PyConfig_SetString(&config, &config.program_name, program);
if (PyStatus_Exception(status)) {
goto exception;
}
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto exception;
}
PyRun_SimpleString(
"import sys\n"
"from time import time,ctime\n"
"print('Today is', ctime(time()))\n"
"print('executable:', sys.executable)\n"
);
if (Py_FinalizeEx() < 0) {
exit(120);
}
PyMem_RawFree(program);
PyConfig_Clear(&config);
return 0;
exception:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}
之后我发现开发版(3.13)的预览文档中包含了一个更新的示例,这个示例去掉了 program
变量,并展示了在运行程序之前可以清空 config
:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
int
main(int argc, char *argv[])
{
PyStatus status;
PyConfig config;
PyConfig_InitPythonConfig(&config);
status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
if (PyStatus_Exception(status)) {
goto exception;
}
status = Py_InitializeFromConfig(&config);
if (PyStatus_Exception(status)) {
goto exception;
}
PyConfig_Clear(&config);
PyRun_SimpleString(
"import sys\n"
"from time import time,ctime\n"
"print('Today is', ctime(time()))\n"
"print('executable:', sys.executable)\n"
);
if (Py_FinalizeEx() < 0) {
exit(120);
}
return 0;
exception:
PyConfig_Clear(&config);
Py_ExitStatusException(status);
}