C++ 从C++;线程,吉尔

C++ 从C++;线程,吉尔,c++,python,C++,Python,请帮帮我。 我尝试从不同的C++线程调用Python脚本,并面临一些问题。 主要内容: Py_Initialize(); PyEval_InitThreads(); PyThreadState *mainThreadState = PyThreadState_Get(); PyEval_ReleaseLock(); PyInterpreterState *mainInterpreterState = mainThreadState->interp; ... //creating t

请帮帮我。
我尝试从不同的C++线程调用Python脚本,并面临一些问题。 主要内容:

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();
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 );
“打印f”显示每个文件的正确文件信息 但是有点不对劲,因为第二个“print f”为不同的线程打印相同的内容,并且输出(如果有)将转到一个文件,而不是每个线程的不同文件
如果我插入time.sleep(1)而不是f.write,则文件处理程序将变得相等 没有什么会崩溃

还尝试使用PyGILState\u确保/PyGILState\u发布,效果相同
主要内容:

储物柜:

TPyScriptThreadLocker:
    PyGILState_STATE m_state;
public:
    TPyScriptThreadLocker(): m_state(PyGILState_Ensure() {}
    ~TPyScriptThreadLocker() { PyGILState_Release(m_state); }
线程对象中的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();
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 );
我知道python中的多线程在大多数情况下都不是个好主意,但现在我想知道这段代码有什么问题

Python 2.7
信息来源

资料来源:
pastebin:

正如我在评论中分析的那样,问题是由于代码中的所有线程都使用相同的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
。不久之后,另一个线程会使它重新定义相同的全局变量。这可能在第一次打印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
将成为一个局部变量。

如果这听起来像个愚蠢的问题,很抱歉,但是如何定义文件名?在你的代码中,它只是说“这个线程的文件”。这个文件名是如何确定的?它只是一个快捷方式,实际上每个线程都有唯一的文件路径,比如QString(“d:\\%1”)。出现正确的文件,第一个f.write工作正常,第二个不正常。。如果我在f.fileno输出之前插入time.sleep(1),也会发生同样的情况,即当我理解时,两个不同的线程同时开始运行(并发)时,您是否有一个最小的示例来说明问题?是的,对于Qt,我将上载它。我怀疑发生的情况是文件的Python变量,
f
,Python解释器将其视为全局线程,并在所有线程之间共享。毕竟,所有线程都在使用同一个解释器实例。尝试创建简单的测试项目,但由于其简单性而遇到问题:)谢谢。