在Objective-C代码中如何获取PyRun_SimpleString的输出字符串?
解决方案
原理说明
PyRun_SimpleString的返回值仅代表Python代码是否执行成功(返回0代表执行无异常,非0代表触发执行错误),本身不会携带代码的执行返回结果,因此你只能在lldb中看到Python解释器的标准输出日志,无法直接拿到返回值。
要获取执行结果可以改用PyRun_String接口,该接口支持直接返回Python表达式的执行对象,你可以将其转换为需要的char*或者NSString类型。
完整实现代码
#import <Python/Python.h> #import <Foundation/Foundation.h> // Python对象转NSString工具方法 NSString* PyObjectToNSString(PyObject *pyObj) { if (!pyObj) return nil; // 转换为Python字符串对象 PyObject *pyStr = PyObject_Str(pyObj); if (!pyStr) { Py_DECREF(pyObj); return nil; } // 转换为UTF8编码的C字符串 const char *cStr = PyUnicode_AsUTF8(pyStr); NSString *result = [NSString stringWithUTF8String:cStr]; // 释放Python对象引用,避免内存泄漏 Py_DECREF(pyStr); Py_DECREF(pyObj); return result; } int main(int argc, const char * argv[]) { @autoreleasepool { // 初始化Python环境 Py_Initialize(); if (!Py_IsInitialized()) { NSLog(@"Python环境初始化失败"); return 1; } // 构造要执行的Python表达式 NSString *checkAttr = @"append"; NSString *commandStr = [NSString stringWithFormat:@"hasattr(list, \"%@\")", checkAttr]; // 执行表达式获取返回对象,Py_eval_input表示执行单个表达式 PyObject *pyResult = PyRun_String( [commandStr cStringUsingEncoding:NSUTF8StringEncoding], Py_eval_input, PyModule_GetDict(PyImport_AddModule("__main__")), PyModule_GetDict(PyImport_AddModule("__main__")) ); // 转成NSString NSString *resultStr = PyObjectToNSString(pyResult); NSLog(@"执行结果字符串:%@", resultStr); // 如需转char* 直接调用:const char *charResult = [resultStr UTF8String]; // 也可以直接转成对应基础类型,比如此处的布尔值 BOOL boolRes = PyObject_IsTrue(pyResult); NSLog(@"布尔类型结果:%d", boolRes); // 清理Python环境 Py_Finalize(); } return 0; }
其他场景说明
如果你需要获取Python代码中print输出的内容,可以通过重定向标准输出实现:
- 先执行代码:
import sys, io; sys.stdout = io.StringIO() - 执行你要运行的业务代码
- 再执行
sys.stdout.getvalue()即可拿到所有print输出的内容,用上述同样的方法转换为NSString即可
注意事项
- 所有Python对象使用完后必须调用
Py_DECREF减少引用计数,避免内存泄漏 - 需在Xcode项目的Build Phases - Link Binary With Libraries中添加
Python.framework,否则会出现编译链接错误 - 如果你使用的是第三方Python发行版,需要对应修改头文件搜索路径和链接库配置
内容的提问来源于stack exchange,提问作者石少卿
相关产品推荐
相关产品推荐

