2012-03-02 56 views
3

请帮助我..
我想从不同的C++线程调用python脚本并遇到一些问题。从C++线程调用python脚本,GIL

主:

Py_Initialize();  
PyEval_InitThreads(); 
PyThreadState *mainThreadState = PyThreadState_Get(); 
PyEval_ReleaseLock(); 
PyInterpreterState *mainInterpreterState = mainThreadState->interp; 
... 
//creating threads with myThreadState per thread 
    PyEval_AcquireLock(); 
    PyThreadState *myThreadState = PyThreadState_New(mainInterpreterState); 
    PyEval_ReleaseLock(); 
//running threads 
... 
PyEval_RestoreThread(mainThreadState); 
Py_Finalize(); 

run()函数在线程对象:

PyEval_AcquireLock(); 
PyThreadState_Swap(m_threadState); 
... 
script = "f = open('file_for_this_thread','w')\n" 
     "print f\n" 
     "f.write('111')\n"      
     "print f.fileno()\n" 
PyRun_SimpleString(script); 
... 
PyThreadState_Swap(NULL); 
PyEval_ReleaseLock(); 

'打印F' 显示正确的文件信息的每个文件 但是,什么是错的,因为第二个“打印˚F '打印相同的不同的线程和输出(如果将有一个)将转到一个文件,而不是每个线程的不同文件
如果我插入time.sleep(1)而不是f.write也是 没有崩溃..

使用PyGILState_Ensure/PyGILState_Release,同样的效果
主也尝试:

Py_Initialize(); 
PyEval_InitThreads(); 
PyThreadState* mainThreadState = PyEval_SaveThread(); 
... 
//creating and running threads 
... 
PyEval_RestoreThread(mainThreadState); 
Py_Finalize(); 

储物柜:

TPyScriptThreadLocker: 
    PyGILState_STATE m_state; 
public: 
    TPyScriptThreadLocker(): m_state(PyGILState_Ensure() {} 
    ~TPyScriptThreadLocker() { PyGILState_Release(m_state); } 

run()函数在线程对象:

TPyScriptThreadLocker lock; 
... 
script = "f = open('file_for_this_thread','w')\n" 
     "print f.fileno()\n" 
     "f.write('111')\n"      
     "print f.fileno()\n" 
PyRun_SimpleString(script); 

我知道了w的蟒蛇是多线程是不是在大多数情况下好主意,但现在我想知道什么是错这个代码..

的Python 2.7
信息从http://www.linuxjournal.com/article/3641?page=0,2

来源:http://files.mail.ru/9D4TEF 引擎收录:http://pastebin.com/DfFT9KN3

+1

对不起,如果这听起来像一个愚蠢的问题,但你如何定义文件名?在你的代码中它只是说''file_for_this_thread'。该文件名称究竟是如何确定的? – jogojapan 2012-03-02 12:34:54

+0

它只是一个快捷方式,实际上每个线程都有独特的文件路径,比如QString(“d:\\%1”)。正确的文件出现,首先f.write工作得很好,其次不是。如果我在f.fileno输出之前插入time.sleep(1),也就是说,当两个不同的线程开始同时运行(同时) – 2012-03-02 13:36:45

+0

你有一个最小的例子来证明问题吗? – James 2012-03-02 13:51:24

回答

1

正如我的意见分析,问题的事实,在代码中的所有线程使用Python解释器,创造了同一个实例,在这里初始化引起的:

Py_Initialize();  

当第一个线程运行在此定义的脚本:

script = "f = open('file_for_this_thread','w')\n" 
     "print f.fileno()\n" 
     "f.write('111')\n"      
     "print f.fileno()\n" 

这将导致Python解释器来分配一个全局Python变量f。此后不久,另一个线程使其重新定义相同的全局变量。这可能不会发生在第一个print f.fileno()时,但它显然发生在第二个之前。

解决方案是确保没有全局变量在线程间共享(或者在每个线程中使用不同的Python解释器实例,并且额外增加内存成本)。

由于目前您的代码中唯一的全局Python变量是f,因此在每个线程中使用f的其他名称就足够了。当你的代码变得更加复杂,这将是更好地界定一个Python功能和使用f(和你需要的任何其他变量)为局部变量:

PyRun_SimpleString(
    "def myfunc(thread_no):\n" 
    " f = open('file_for_thread_%d' % thread_no,'w')\n" 
    " print f.fileno()\n" 
    " f.write('111')\n"    
    " print f.fileno()\n" 
); 

以上会被应用只有一次并在任何线程运行之前运行

在每个线程,你会再简单地做

PyRun_SimpleString(QString("myfunc(%d)\n",current_thread_no)); 

即线程只会调用Python函数,并且f将成为局部变量。

+0

试图做简单的测试项目,并得到了问题,因为它简单:)谢谢。 – 2012-03-02 16:07:41