You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Python C API从C字符串中的lambda代码生成PyObject?

问题:通过Python C API将字符串形式的Lambda转为PyObject

原Python实现

使用pyjexl添加小写转换功能的Python代码:

import pyjexl

jexl = pyjexl.JEXL()
jexl.add_transform("lowercase", lambda x: str(x).lower())

目标C API实现(待完善)

希望通过Python C API实现相同功能,目前代码框架如下(已省略空指针检查和引用计数管理):

Py_Initialize();
PyObject* pyjexlModule = PyImport_ImportModule("pyjexl");
PyObject* jexl = PyObject_CallMethod(pyjexlModule, "JEXL", NULL);

const char* myLambda = "lambda x: str(x).lower()";
PyObject* lambda = ... /* 需要实现的核心部分 */
PyObject_CallMethod(jexl, "add_transform", "sO", "lowercase", lambda);

遇到的问题

尝试用PyRun_String转换lambda字符串,但调试发现生成的lambda变量为PyNone类型,使用的代码片段:

PyObject* globals = PyDict_New();
PyObject* locals = PyDict_New();
PyObject* lambda = PyRun_String(myLambda, Py_eval_input, globals, locals);

解决方案

问题根源是新建的globals字典缺少__builtins__引用,导致lambda表达式中的str内置函数无法被解析,执行出错后返回NULL(表现为PyNone)。修正后的代码如下:

方案1:直接使用当前全局环境(推荐)

const char* myLambda = "lambda x: str(x).lower()";
// 获取当前Python解释器的全局环境,已包含__builtins__
PyObject* globals = PyEval_GetGlobals();
PyObject* locals = PyDict_New();
PyObject* lambda = PyRun_String(myLambda, Py_eval_input, globals, locals);

// 检查执行结果
if (!lambda) {
    PyErr_Print(); // 打印错误信息用于调试
} else {
    PyObject_CallMethod(jexl, "add_transform", "sO", "lowercase", lambda);
}

// 管理引用计数
Py_XDECREF(locals);
Py_XDECREF(lambda);

方案2:手动构建含内置模块的全局字典

如果需要自定义全局环境,可以手动添加__builtins__引用:

const char* myLambda = "lambda x: str(x).lower()";
PyObject* globals = PyDict_New();
PyObject* builtins = PyImport_ImportModule("builtins");
PyDict_SetItemString(globals, "__builtins__", builtins);
Py_DECREF(builtins);

PyObject* locals = PyDict_New();
PyObject* lambda = PyRun_String(myLambda, Py_eval_input, globals, locals);

// 检查执行结果
if (!lambda) {
    PyErr_Print();
} else {
    PyObject_CallMethod(jexl, "add_transform", "sO", "lowercase", lambda);
}

// 管理引用计数
Py_XDECREF(globals);
Py_XDECREF(locals);
Py_XDECREF(lambda);

关键说明

  • 必须确保全局环境中存在__builtins__,否则内置函数(如str)无法被lambda表达式访问
  • 调用PyRun_String后必须检查返回值,若为NULL则代表执行出错,PyErr_Print()可以输出具体错误信息辅助调试

内容的提问来源于stack exchange,提问作者fgalan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 12:04:54