搜索
aardio官方社区 门户 查看主题

多线程中使用Python

发布者: 雨林枫1234 | 发布时间: 2017-12-24 21:05| 查看数: 499| 评论数: 3|帖子模式

在多线程中调用Python会出现内存错误,代码如下
  1. import console;

  2. thread_func = function( i ){
  3.     import console;
  4.         console.open();
  5.     import py;

  6.         var pyCode = /**
  7. def add(a,b):
  8.     return a + b
  9. **/
  10.         py.exec( pyCode );//运行Python代码
  11.         var num = py.main.add( i , i + 1);
  12.         console.log(num)
  13. }

  14. for(i=1; 2;1){
  15.         thread.create(thread_func,i);
  16. }

  17. console.pause(true);
复制代码

最新评论

Jacen.He 发表于 2018-4-8 23:32:41
Pyhton并不支持真正的多线程,在多线程环境下运行需要通过GIL实现互斥运行,py扩展库新版范例里的代码:
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=1163;bottom=753)
winform.add(
button={cls=
"button";text="button";left=876;top=663;right=1102;bottom=723;z=2};
edit={cls=
"edit";left=11;top=16;right=1140;bottom=625;edge=1;multiline=1;z=1}
)
/*}}*/

/*
要点1、一定要在主线程导入python库
主线程会负责创建python虚拟机,主线程退出不能再在任何线程调用python.
*/

import py;

/*
要点2、一定要在主线程释放GIL,之后任何python调用都在在py.lock里执行
注意,只有你确实要在多个线程并发调用python时,才需要使用GIL。
*/

py.releaseThread();

pyThread =
function(winform){
   
import py;
   
   
/*
    要点3、启用GIL以后,任何python调用都必须在py.lock里执行
    python并不支持真正的多线程,所有调用都要加锁互斥运行。
    */

    py.lock(
        
function(){
            
var hashlib = py.import("hashlib");
            
var md5 = hashlib.md5()
            md5.update( raw.buffer(
"注意这个函数的参数不是字符串而是字节数组(相当于aardio中的buffer)") );
            winform.edit.print(thread.getId(),
tostring(md5.hexdigest()) );                 
        }
    )
}


winform.button.oncommand =
function(id,event){
   
   
for(i=1;10;1){
        thread.invoke( pyThread,winform )  
    }
}

winform.show()
win.loopMessage();



Jacen.He 发表于 2018-4-8 23:33:48
更好的方式是使用单个后台线程来运行python,示例:
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio - 后台线程运行Python";right=1163;bottom=753)
winform.add(
button={cls=
"button";text="调用python线程";left=876;top=663;right=1102;bottom=723;z=2};
edit={cls=
"edit";left=11;top=16;right=1140;bottom=625;edge=1;multiline=1;z=1}
)
/*}}*/

/*
其实Python并不支持真正的多线程,
Pyhton的多线程GIL管理也不方便,处理不好就会崩溃、死锁。

所以更好的方式是在单线程中运行python,
如果在界面线程中,python需要做耗时操作,
那么可以使用工作线程运行python,下面是一个演示:
*/


//python服务端线程
pyServerThread = function(winform){
   
import thread.command;
   
import py;
   
   
//创建命令监听器
    var cmd = thread.command();
   
   
//响应事件
    cmd.pyHash = function(){   
        
        
//可以直接访问界面控件
        winform.edit.print("子线程正在执行pyHash函数",tostring(time()))
        
        
var hashlib = py.import("hashlib");
        
var md5 = hashlib.md5()
        md5.update( raw.buffer(
"注意这个函数的参数不是字符串而是字节数组(相当于aardio中的buffer)") );   
        
sleep(1000)
        
        
//调用界面线的函数
        winform.pyHashEnd( tostring(md5.hexdigest()) );
        
        
return tostring(md5.hexdigest());
    }
   
   
//退出线程
    cmd.pyExit = function(){
        win.quitMessage();
    }

   
//在工作线程需要启用消息循环,才能响应事件
    win.loopMessage();  
}

//启动python服务端线程
thread.create( pyServerThread,winform )

//增加工作线程可以调用的函数
winform.pyHashEnd = function(str){
    winform.edit.print(
"主线程收到:",str)
}

import thread.command;
winform.button.oncommand =
function(id,event){
      
   
//禁用按钮,避免重复提交
    winform.button.disabledText = "正在调用python线程";
   
   
//异步调用python线程的函数,不等待返回
    thread.command.post("pyHash")
   
   
//异步调用python线程的函数,等待返回值
    var str = thread.command.sendInvoke("pyHash")
    winform.edit.print(
"主线程收到:",str)
   
   
//取消按钮禁用状态
    winform.button.disabledText = null;
}  

winform.onClose =
function(hwnd,message,wParam,lParam){
   
//退出Python线程
    thread.command.pyExit()
}

winform.show()
win.loopMessage();

Jacen.He 发表于 2018-4-8 23:35:00
如果能保证在一个进程里,只在一个线程里使用python,那就很简单了,不需要处理这些问题,python在单线程下工作是没问题的。

手机版|未经许可严禁引用或转载本站文章|站长邮箱|aardio.com|aardio官方社区 ( 皖ICP备09012014号 )

GMT+8, 2018-4-23 21:38 , Processed in 0.062518 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表