Python与C/C++多线程:在C后台运行多个执行Python的线程

2 投票
2 回答
1216 浏览
提问于 2025-04-17 22:31

我有一个很具体的需求:我想用Qt小部件创建一个Python控制台,并且能够拥有多个独立的解释器。现在让我试着解释一下我遇到的问题和我所做的尝试,按照我最希望能成功的顺序排列到那些我可以默认使用的。

  • 首先,Python的C API中的所有函数(比如PyRun[...]、PyEval[...]等)都需要锁定全局解释器锁(GIL),这就意味着不能同时从C代码中运行多个解释器(如果我错了我会很高兴!!! :D)

  • 因此,我尝试了一种不同于“常规方法”的方法:我在Python中做了一个循环,调用read()从我的特殊文件中读取数据,并对结果进行评估。这个函数(作为一个内置扩展实现)会阻塞,直到有数据可读。(实际上,现在这是在C代码中的一个while循环,而不是基于pthread的条件)然后,我用PyRun_simpleString()在另一个线程中启动我的循环。这就是问题所在:我的read函数除了会阻塞当前线程(这完全正常),还会阻塞整个解释器,而PyRun_simpleString()不会返回...

  • 最后,我有了这个最后的想法,可能会比较慢:在C++中有一个专门的线程来运行解释器,所有的输入/输出管理都在Python中进行。这可以是一个循环,当有控制台需要执行命令时创建任务。看起来并不是特别难,但我更想问你:有没有办法让上述可能性工作,或者有没有我没想到的其他方法,还是我的最后想法是最好的?

2 个回答

0

如果你主要的需求是让几个解释器彼此独立,那么使用fork()和exec()可能会比多线程更合适。

这样,每个解释器都会在自己的地址空间中运行,互不干扰。

3

一种替代方案是直接重用IPython和它的Qt控制台中的代码。这是基于你提到的“独立解释器”意味着它们不会共享内存的假设。IPython会在多个进程中运行Python解释器,并通过TCP或Unix域套接字与它们进行通信,使用的是ZeroMQ这个工具。

另外,从你的问题来看,我不确定你是否了解Python C扩展中的常见阻塞I/O模式:

Py_BEGIN_ALLOW_THREADS
... Do some blocking I/O operation ...
Py_END_ALLOW_THREADS

这个模式会释放全局解释器锁(GIL),这样在你的函数阻塞的时候,其他线程就可以执行Python代码。你可以查看Python/C API参考手册:线程状态和全局解释器锁来了解更多。

撰写回答