在C程序中嵌入多个Python子解释器

2024-09-30 16:39:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个生成多个C线程的C程序,每个线程有一个Python子解释器。子解释器不共享任何可变的Python变量,它们相互隔离。(它们对从C程序的main()函数公开的公共PyObject(不可变)具有只读访问权限)。在

在python3.7或3.8中,不在子解释器之间共享GIL,这是否可能?在

以下是我一直在尝试的伪代码:

void *spawnInterpreter(void* p) {
    …
    PyThreadState* save_tstate = PyThreadState_Swap(NULL);
    PyThreadState* tstate = Py_NewInterpreter();
    PyThreadState_Swap(save_tstate);

    //do some Python work (with variables that are NOT shared with other thread’s sub-interpreter
    PyRun_SimpleString( . . .);
    . . . 
}


int main() {
...
    pthread_create(&thread1, NULL, spawnInterpreter,  “in1”);
    pthread_create(&thread2, NULL, spawnInterpreter, "in2");
...
}

我可以让它在3.6中工作(不需要获取GIL或在C线程中管理PyThreadState),但是在python3.7中我得到了:

^{pr2}$

Tags: 程序mainsavecreatewith线程解释器null
1条回答
网友
1楼 · 发布于 2024-09-30 16:39:57

不幸的是,在3.7和3.8中,分译器仍然共享GIL。这是我个人正在努力改变的。请参见PEP 554my multi-core Python project。下周我还将提供a talk at PyCon,详细介绍这个主题。在

我希望在Python3.8中实现这一点,但现在看来3.9更有可能实现。主要的挑战是C-API和CPython运行时不是线程安全的。虽然大多数C-API和运行时都可以切换到使用每解释器GIL,但在这种情况下,其他事情必须改变:

  • 一些进程全局资源必须在没有GIL的情况下进行更仔细的管理(例如env vars、文件句柄)
  • 解释器必须继续共享全局运行时状态,因此很多内容仍然必须受到全局锁的保护(尽管将而不是的锁需要阻止Python字节码eval循环)
  • 一些全局运行时状态需要下移到每个解释器状态(例如GC、内存分配器、警告)
  • 对象将需要严格按照每个解释器(现在),因此C-API必须严格禁止对象跨越解释器边界
  • C-API中不特定于解释器上下文的部分必须更改为不再需要持有GIL

这个问题是可以解决的,但是在处理这种关键代码时,需要花时间来应用必要的注意。因此可能的目标是3.9。在


不管怎样,我很感谢你在这里发帖。我的大部分工作都集中在对Python代码的影响上,而不是C-API(例如嵌入程序)。因此,关于我的项目如何通过C-API使用子解释器的反馈非常有用。对于55ve实例来说,创建一个与创建一个PEP-4的API有点不同。这需要更仔细地考虑。另外,pep554几乎没有在C-API中公开它的任何添加。这可能没问题,但从短期来看,与C-API中的通道交互可能很有价值。在

相关问题 更多 >