如何通过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
相关产品推荐
相关产品推荐

