Boost Python的多线程问题

来源:互联网 发布:音频编辑软件有哪些 编辑:程序博客网 时间:2024/06/01 15:27

      因为工作中一个项目需要在运行过程中支持可以随时修改和便于管理的运行流程和配置参数管理,所以决定使用嵌入Python的方式实现,但是项目是多线程的,所以需要确定Boost Python的多线程支持程度,做了一些尝试。

 

1、Boost Python不支持多线程:

     使用Boost ThreadPool简化多线程环境,尝试如下:

 

void Pytest1()
{
Py_Initialize();
PyRun_SimpleString("from time import time,ctime/n"
      "print 'Today is',ctime(time())/n");
Py_Finalize();
}


void do_task()
{
for (int i = 0; i < 10; ++i)
{

Pytest1();
}

boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); // initialize xt with current time
xt.sec += 1; // change xt to next second
boost::thread::sleep(xt); // do sleep
}

void Pytest3()
{
pool tp(5);

Py_Initialize();
// Add some tasks to the pool.
for (int i = 0 ; i <= 5; ++i)
{
tp.schedule(&do_task);
}
// Wait until all tasks are finished.
tp.wait();
Py_Finalize();
}

 

 

程序运行失败,报运行异常信息,看来直接在多线程中使用Boost Python不行。

 

2、在多线程中采用锁保护,实现Python运行环境的多线程串行化运行:

     尝试如下:

 

boost::mutex m_io_monitor;

 

void do_task()
{
for (int i = 0; i < 10; ++i)
{
{
boost::mutex::scoped_lock lock(m_io_monitor);
PyRun_SimpleString("from time import time,ctime/nprint 'Today is',ctime(time())/n");
}

boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); // initialize xt with current time
xt.sec += 1; // change xt to next second
boost::thread::sleep(xt); // do sleep
}
}

void Pytest3()
{
pool tp(5);

Py_Initialize();
// Add some tasks to the pool.
for (int i = 0 ; i <= 5; ++i)
{
tp.schedule(&do_task);
}
// Wait until all tasks are finished.
tp.wait();
Py_Finalize();
}

 

运行完全正常。

 

3、在多线程中采用锁保护,实现Python调用脚本的多线程串行化运行:

 

 

boost::mutex m_io_monitor;


void do_task()
{
for (int i = 0; i < 10; ++i)
{

{

boost::mutex::scoped_lock lock(m_io_monitor);


object main_module = import("__main__");
object main_namespace = main_module.attr("__dict__");

 
object simple = exec_file("simple.py",main_namespace, main_namespace);
object foo = main_namespace["foo"];
int val = extract<int>(foo(5));

 

cout << "Python has caculated foo as " << val << endl;
}

boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC); // initialize xt with current time
xt.sec += 1; // change xt to next second
boost::thread::sleep(xt); // do sleep
}
}

 

 

运行成功。

 

总结:

     1、有时间需要跟踪分析一下Python的代码,确定不能多线程并行运行的原因

     2、Python可以在多线程环境中运行,但是必须要将整个运行过程用保护锁保护起来,强制Python的运行采用串行化的方式

     3、Py_Initialize()与Py_Finalize()可以预先在进程中由进程启动和释放,不要在每一个线程中调用。

     4、由于Python的运行必须串行化,所以需要注意其运行效率,不要用Python执行需要长时间的任务。