既然 Py_SetProgramName() 已弃用,如何设置 Python 可执行文件名称?

问题描述 投票:0回答:1

用于嵌入的 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.

生成的可执行文件将运行,如果您将

import sys
print(sys.executable)
添加到
PyRun_SimpleString()
参数,则会显示正确的可执行文件名称。

虽然这在 3.11 中已被弃用,并且在 3.12 中仍然推荐,但我宁愿摆脱警告。我该如何更改程序?

python c python-c-api
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);
}

后来我发现dev(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);
}
© www.soinside.com 2019 - 2024. All rights reserved.