由于Python解释器有全局解释所GIL的原因,导致在同一时刻只能有一个线程拥有解释器,所以在C++多线程调用python脚本时,需要控制GIL,线程获取GIL。
在主线程中初始化Python解释器环境,代码如下:
if ( !Py_IsInitialized() )
int nInit = PyEval_ThreadsInitialized();
然后可以创建子线程,在子线程调用中 加入如下代码:
int nHold = PyGILState_Check() ;
gstate = PyGILState_Ensure();
PyGILState_Release(gstate);
boost::python对Python原生的C API有较好的封装,可以很方便通过C++对python脚本进行调用一下是一些学习总结,以便今后需要使用的时候能快速使用
假设有python模块 School.py 包含类 Student 和 函数 Call 和返回类对象的CallClass方法
def __init__(name,age,properties):
self.properties = proterties
print(self.name, slef.age, self.properties)
s = Student("universal",20,"good")
以下为C++调用python脚本代码:
1> 在C++中构造python中定义的类,并且调用类方法
boost::python::handle<>* school_module = NULL;
string strModule = "School";
school_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
boost::python::object main_module(*manager_module);
boost::python::object main_namespace = main_module.attr("__dict__");
boost::python::handle<> Student;
Student = boost::python::handle<>((PyRun_String(
"Student('alen',30,{\"errorcode\":0, \"message\":\"execute succeed\"})", Py_eval_input,
main_namespace.ptr(), main_namespace.ptr())));
2>调用脚本中的函数 Call 假设传递的第一个参数为string 第二个为int
boost::python::handle<>* school_module = NULL;
string strModule = "School";
school_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
boost::python::object result = boost::python::call_method<boost::python::object>(school_module->get(),"Call","schoolname",2);
3>调用脚本时,可以传递各种参数,boost 已经封装了boost::python::dict 对应dict boost::python::tuple对应 tuple
比如构造dict参数,代码如下:
boost::python::dict inParams;
inParams.setdefault<std::string,std::string>("name","clear");
inParams.setdefault<std::string,std::string>("code","56821334");
inParams.setdefault<std::string,int>("number",123456);
4>处理返回的数据比如 python类类型
boost::python::handle<>* school_module = NULL;
string strModule = "School";
school_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
boost::python::object student = boost::python::call_method<boost::python::object>(school_module->get(),"CallClass");
boost::python::object q = boost::python::call_method<boost::python::object>(student.ptr(), "show");
boost::python::object obj_dict = student.attr("__dict__");
boost::python::object name = obj_dict["name"];
std::string sname = boost::python::extract<std::string>(name);
boost::python::object age = obj_dict["age"];
int age = boost::python::extract<int>(age);
将全局解释器锁和线程的相关操作用类封装,使用构造函数和析构函数 去做locker 和 unlocker的操作
nStatus = PyGILState_Check() ;
gstate = PyGILState_Ensure();
_save = PyEval_SaveThread();
PyEval_RestoreThread(_save);
_save = PyEval_SaveThread();
PyEval_RestoreThread(_save);
PyGILState_Release(gstate);
在代码中调用时,只需要
使用boost::python的时候捕获异常获取异常信息
std::string GetPythonErrorInfo(void)
using namespace boost::python;
PyErr_Fetch(&exc,&val,&tb);
PyErr_NormalizeException(&exc,&val,&tb);
handle<> hexc(exc),hval(allow_null(val)),htb(allow_null(tb));
return extract<std::string>(str(hexc));
object traceback(import("traceback"));
object format_exception(traceback.attr("format_exception"));
object formatted_list(format_exception(hexc,hval,htb));
object formatted(str("").join(formatted_list));
return extract<std::string>(formatted);
以下为VC控制台测试程序
#include <boost/python.hpp>
#define Check_Init(init) \
cout<<"请先通过init指令初始化python环境"<<endl;\
std::string strModule = "manager";
unsigned int __stdcall ThreadCall(void* lparam)
char szMessage[1024] = { 0 };
int id = GetCurrentThreadId();
sprintf_s(szMessage,sizeof(szMessage),"thread id: %d ",id);
std::string sResult = "";
boost::python::handle<>* manager_module = NULL;
for ( int i = 0 ; i < 2000 ; i ++)
manager_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
sResult = boost::python::call_method<std::string>(manager_module->get(),"threadcall",szMessage);
cout<<sResult.c_str()<<endl;
void callsay(const char* szMessage)
boost::python::handle<>* manager_module = NULL;
std::string sResult = "";
manager_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
sResult = boost::python::call_method<std::string>(manager_module->get(),"say",szMessage);
cout<<"捕获一个异常在callsay方法中"<<endl;
int _tmain(int argc, _TCHAR* argv[])
while ( strcmp("quit",szCommand) != 0 )
if ( strcmp("threadcall",szCommand) == 0 )
for ( int i = 0 ; i < 5; i++ )
else if ( strcmp("init",szCommand) == 0 )
cout<<"Python 环境已经初始化"<<endl;
if ( !Py_IsInitialized() )
cout<<"Python环境初始化失败"<<endl;
int nInit = PyEval_ThreadsInitialized();
cout<<"Python环境初始化成功,退出前请使用free指令释放Python环境"<<endl;
else if ( strcmp("say",szCommand) == 0 )
std::string msg = "Python Manager";
else if ( strcmp("free",szCommand) == 0 )
cout<<"Python解释器环境被释放"<<endl;
添加一个测试过程中的代码, 因为还封装了类所以单独编译不过,用来标记一下吧 ,方便下次在使用的时候可以快速的重新学习
#include "PythonAssister.h"
#define Check_Init(init) \
cout<<"请先通过init指令初始化python环境"<<endl;\
std::string strModule = "manager";
unsigned int __stdcall ThreadCall(void* lparam)
char szMessage[1024] = { 0 };
int id = GetCurrentThreadId();
sprintf_s(szMessage,sizeof(szMessage),"thread id: %d ",id);
std::string sResult = "";
boost::python::handle<>* manager_module = NULL;
for ( int i = 0 ; i < 2000 ; i ++)
manager_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
sResult = boost::python::call_method<std::string>(manager_module->get(),"threadcall",szMessage);
cout<<sResult.c_str()<<endl;
boost::python::handle<>* manager_module = NULL;
manager_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
boost::python::object result = boost::python::call_method<boost::python::object>(manager_module->get(),"calltest");
cout<< result.ptr()->ob_type->tp_name<<endl;
boost::python::object q = boost::python::call_method<boost::python::object>(result.ptr(), "show");
boost::python::object r1 = result.attr("__dict__");
boost::python::object r2 = r1["name"];
std::string sname = boost::python::extract<std::string>(r2);
cout<<sname.c_str()<<endl;
boost::python::handle<>* manager_module = NULL;
manager_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
boost::python::object main_module(*manager_module);
boost::python::object main_namespace = main_module.attr("__dict__");
boost::python::handle<> Student;
Student = boost::python::handle<>((PyRun_String(
"Student('alen',30,{\"errorcode\":0, \"message\":\"execute succeed\"})", Py_eval_input,
main_namespace.ptr(), main_namespace.ptr())));
boost::python::object result = boost::python::call_method<boost::python::object>(Student.get(), "show");
boost::python::handle<>* manager_module = NULL;
boost::python::dict mydict;
int nHold = PyGILState_Check() ;
gstate = PyGILState_Ensure();
boost::python::dict inParams;
inParams.setdefault<std::string,std::string>("name","clear");
inParams.setdefault<std::string,std::string>("code","56821334");
inParams.setdefault<std::string,int>("number",123456);
int nLenDict = len(inParams);
const char* szType = inParams.ptr()->ob_type->tp_name;
boost::python::list dictlist;
dictlist = inParams.items();
int nLenList = len(dictlist);
for ( int i = 0 ; i< nLenList; i++ )
boost::python::object obj;
const char* szType = obj.ptr()->ob_type->tp_name;
int n = PyType_Check(obj.ptr());
int nLenTuple = len(obj);
for ( int j = 0 ; j <nLenTuple; j++ )
int n1 = PyType_Check(((boost::python::object)obj[j]).ptr());
std::string value = boost::python::extract<std::string>(obj[j]);
boost::python::extract<const std::string&>ex((obj[j]));
cout<<"yes it is string"<<endl;
cout<<value.c_str()<<endl;
boost::python::object itemTuple;
itemTuple = dictlist.pop();
while ( itemTuple != NULL )
int nLen = len(itemTuple);
string strKey = boost::python::extract<std::string>(itemTuple[0]);
string strValue = boost::python::extract<std::string>(itemTuple[1]);
itemTuple = dictlist.pop();
manager_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
boost::python::object result = boost::python::call_method<boost::python::object>(manager_module->get(),"calldict",inParams);
const char* szType1 = result.ptr()->ob_type->tp_name;
cout<<"Type : "<<szType1<<endl;
cout<<"捕获一个异常在calldict方法中"<<endl;
if ( NULL != manager_module )
PyGILState_Release(gstate);
void callsay(const char* szMessage)
boost::python::handle<>* manager_module = NULL;
std::string sResult = "";
int nHold = PyGILState_Check() ;
gstate = PyGILState_Ensure();
manager_module = new boost::python::handle<>(PyImport_ImportModule((char*)strModule.c_str()));
sResult = boost::python::call_method<std::string>(manager_module->get(),"say",szMessage);
cout<<"捕获一个异常在callsay方法中"<<endl;
PyGILState_Release(gstate);
int _tmain(int argc, _TCHAR* argv[])
while ( strcmp("quit",szCommand) != 0 )
if ( strcmp("threadcall",szCommand) == 0 )
for ( int i = 0 ; i < 5; i++ )
else if ( strcmp("classtest",szCommand) == 0 )
else if ( strcmp("init",szCommand) == 0 )
cout<<"Python 环境已经初始化"<<endl;
if ( !Py_IsInitialized() )
cout<<"Python环境初始化失败"<<endl;
int nInit = PyEval_ThreadsInitialized();
cout<<"Python环境初始化成功,退出前请使用free指令释放Python环境"<<endl;
else if ( strcmp("say",szCommand) == 0 )
std::string msg = "Python Manager";
else if ( strcmp("calldict",szCommand) == 0 )
std::string msg = "Python Manager";
else if ( strcmp("free",szCommand) == 0 )
int nHold = PyGILState_Check() ;
gstate = PyGILState_Ensure();
cout<<"Python解释器环境被释放"<<endl;
ref:(188条消息) C++ 多线程调用Python脚本_追风弧箭的博客-CSDN博客_c++多线程调用python
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
2019-01-30 双网卡单IP实现网卡冗余与负载均衡
2018-01-30 live555源码分析----RSTPServer创建过程分析