c单线程及多线程处理python

1. c单线程处理python

……
#include <python3.7m/Python.h>
……


/* 	
	其他初始化处理
	pcRespJson 接收python函数返回值 如果有的话
*/
const  char *pcRespJson       = NULL;

/* python 对象初始化 */
PyObject *pstName     = NULL;
PyObject *pstModule   = NULL;
PyObject *pstFunc     = NULL;
PyObject *pstArgvs    = NULL;
PyObject *pstRetValue = NULL;

/* python 初始化 */
Py_Initialize(); //初始化Python环境
if ( !Py_IsInitialized() ) //检测是否初始化成功
{
	printf("\r\nPy_IsInitialized() failed \r\n");
	return 1;
}

/* 下面处理 python */
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");

/* python 文件名称 print_hello.py */	
pstName = PyUnicode_FromString("print_hello");
pstModule = PyImport_Import(pstName);
Py_DECREF(pstName);

if(pstModule != NULL)
{
	/* print_hello.py 中的函数名称 myPrint */	
    pstFunc = PyObject_GetAttrString(pstModule, "myPrint");
    if((pstFunc == NULL) || (PyCallable_Check(pstFunc) == BOOL_FALSE))
    {
	    Py_DECREF(pstModule);
        return ERROR_FAILED;
	}

	/* 函数 myPrint 需要几个参数,可以多个*/
    pstArgvs = PyTuple_New(2);

    PyTuple_SetItem(pstArgvs, 0, Py_BuildValue("s", “name”));
    PyTuple_SetItem(pstArgvs, 1, Py_BuildValue("s", "time"));

	/* 调用 myPrint 函数处理 */
    pstRetValue = PyObject_CallObject(pstFunc, pstArgvs);
    Py_DECREF(pstArgvs);
    
    if(pstRetValue == NULL)
	{
        Py_DECREF(pstFunc);
        Py_DECREF(pstModule);
        return ERROR_FAILED;
    }
	
	/* myPrint 函数返回值转码处理 */
    pcRespJson = PyUnicode_AsUTF8(pstRetValue);
    if(pcRespJson == NULL)
    {
    	/* 如果python 有 json 返回值*/
        pcRespJson = PyBytes_AsString(pstRetValue);
    }
    
    if(pcRespJson != NULL)
    {
        /* 
			处理返回 json 串 pcRespJson
			……
			……
		*/
		
    }

    Py_DECREF(pstRetValue);
    Py_DECREF(pstFunc);
    Py_DECREF(pstModule);
}

/* python 去初始化 */
Py_Finalize();

2. c多线程处理 python 踩坑教训

  1. 在项目中一定是只初始化一次,最后摧毁一次
    建议不要反复创建摧毁Py模块
    否则,会出现一些异常错误还有段错误。

  2. 编译的时候带上: -lpython3.7m

  3. https://bbs.csdn.net/topics/390824020
    Py_Initialize(); // //谁初始化谁释放原则,实际使用中需要存一个值判定是否是自己初始化的
    Py_Finalize();//摧毁好像会不完全摧毁,导致许多奇怪问题

    多线程使用我不清楚,但是我在项目中一定是只初始化一次,最后摧毁一次
    建议LZ不要反复创建摧毁Py模块

2.1 主线程 初始化代码

void Thread_Init()
{
	int iRet = 0;
	
	Py_Initialize(); //初始化Python环境
	if ( !Py_IsInitialized() ) //检测是否初始化成功
	{
		printf("\r\nPy_IsInitialized() failed \r\n");
		return 1;
	}
	else
	{
		PyEval_InitThreads();     //开启多线程支持
		PyEval_ReleaseThread(PyThreadState_Get()); 
	}
}

2.2 主线程 去初始化代码

void Thread_Exit()
{ 
	PyGILState_Ensure() ;
	Py_Finalize();
	return ;
}

2.3 c多线程python处理:

……
#include <python3.7m/Python.h>
……

/* pcRespJson 接收python函数返回值 */
const  char *pcRespJson       = NULL;

/* python 对象初始化 */
PyObject *pstName     = NULL;
PyObject *pstModule   = NULL;
PyObject *pstFunc     = NULL;
PyObject *pstArgvs    = NULL;
PyObject *pstRetValue = NULL;

/* 线程python 初始化 */
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();   //如果没有GIL,则申请获取GIL
Py_BEGIN_ALLOW_THREADS;
Py_BLOCK_THREADS;

/* 下面处理 python */
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");

/* python 文件名称 print_hello.py */	
pstName = PyUnicode_FromString("print_hello");
pstModule = PyImport_Import(pstName);
Py_DECREF(pstName);

if(pstModule != NULL)
{
	/* print_hello.py 中的函数名称 myPrint */	
    pstFunc = PyObject_GetAttrString(pstModule, "myPrint");
    if((pstFunc == NULL) || (PyCallable_Check(pstFunc) == BOOL_FALSE))
    {
	    Py_DECREF(pstModule);
        return ERROR_FAILED; /* ERROR_FAILED 这是个返回值的宏 1 */
	}

	/* 函数 myPrint 需要几个参数,可以多个*/
    pstArgvs = PyTuple_New(2);

    PyTuple_SetItem(pstArgvs, 0, Py_BuildValue("s", “name”));
    PyTuple_SetItem(pstArgvs, 1, Py_BuildValue("s", "time"));

	/* 调用 myPrint 函数处理 */
    pstRetValue = PyObject_CallObject(pstFunc, pstArgvs);
    Py_DECREF(pstArgvs);
    
    if(pstRetValue == NULL)
	{
        Py_DECREF(pstFunc);
        Py_DECREF(pstModule);
        return ERROR_FAILED;
    }
	
	/* myPrint 函数返回值转码处理 */
    pcRespJson = PyUnicode_AsUTF8(pstRetValue);
    if(pcRespJson == NULL)
    {
    	/* 如果python 有 json 返回值*/
        pcRespJson = PyBytes_AsString(pstRetValue);
    }
    
    if(pcRespJson != NULL)
    {
        /* 
			处理返回 json 串 pcRespJson
			……
			……
		*/
		
    }

    Py_DECREF(pstRetValue);
    Py_DECREF(pstFunc);
    Py_DECREF(pstModule);
}

/* 线程python 去初始化 */
Py_UNBLOCK_THREADS;
Py_END_ALLOW_THREADS;
PyGILState_Release(gstate);    //释放当前线程的GIL

2.4 多线程python处理异常处理-踩坑

某个线程1加锁处理任务时出错了需要及时释放锁,否则另外一个线程会卡死在取锁的地方或者其他python处理的地方。

现象:代码会卡在不同的地方
有的是调用python 前后几行,或者python脚本里面不同的地方。

//异常情况处理释放当前线程锁GIL
if (!nHold)
{
	PyGILState_Release(gstate);    //释放当前线程的GIL
}

参考:

https://www.csdn.net/gather_23/NtTaAg4sMzItYmxvZwO0O0OO0O0O.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值