如何通过多处理在单独的Python进程中使用Cython包装的外部C库?

时间:2017-09-27 20:16:08

标签: python c python-3.x cython python-multiprocessing

我在Cython中包装了一个小型C库,并且可以从Python成功调用它。这是一个简化的例子,表示现在的情况:

# wrapper_module.pyx

cdef extern from "my_c_library.h":
    void function1()
    int function2(int param1, char *param2)

class MyWrapperClass():
    def __init__(self):
        pass
    def do_func1(self):
        function1()
    def do_func2(self, p1, p2):
        function2(p1, p2)

这一切都运作良好。我现在的目标是在一个单独的过程中创建和使用MyWrapperClass的实例,如下所示:

# my_script.py

import multiprocessing as mp
from wrapper_module import MyWrapperClass

class MyProcess(mp.Process):
    def __init__(self):
        super().__init__()

    def run(self):
        self.mwc = MyWrapperClass()
        self.mwc.do_func1()
        # ... do more

if __name__ == '__main__':
    proc = MyProcess()
    proc.start()

当我运行my_script.py时,我收到以下错误:

  

该进程已分叉,您无法使用此CoreFoundation   功能安全。你必须exec()。打断   的 THE_PROCESS_HAS_FORKED_AND_YOU_CANNOT_USE_THIS_COREFOUNDATION_FUNCTIONALITY ___ YOU_MUST_EXEC ()   调试。

我想我一般都明白为什么它不允许将这个cython模块分成不同的进程(由于底层C库使用的资源)。但通常当我在过去遇到过这种类型的问题时,无论是纯Python还是使用ctypes并调用DLL,我都可以通过将所有关键代码放在run MyProcess方法中来解决它,导致它只在新分叉的进程中初始化。

但是,在这个Cython案例中,我不知道如何仅在分叉进程中包含cdef extern代码,以避免此错误。有什么建议吗?

(我在macOS 10.12上运行python 3.6.2)

1 个答案:

答案 0 :(得分:0)

cdef extern中的代码只是外部c函数的延迟(我们只考虑c),这些delarations被放入生成的c文件中而没有任何变化(差不多),它与之无关初始化。

我也做了一个相当简单的测试(py3.6 windows):

<强> lib.c:

int add(int a, int b)
{
    return a + b ;
}

<强> mylib.pyx:

cdef extern from "lib.c":
    int _add "add"(int a, int b)

cdef class WrapperClass:
    def add(self, a, b):
        return _add(a, b)

<强> test_lib.py:

from mylib import WrapperClass
import multiprocessing as mp

class MyProcess(mp.Process):
    def __init__(self):
        super().__init__()

    def run(self):
        self.mwc = WrapperClass()
        print(self.mwc.add(1, 2))


if __name__ == "__main__":
    proc = MyProcess()
    proc.start()

运行python test_lib.py没有任何问题。也许我的c代码太简单了,但我不知道你的c函数究竟做了什么,真的是真正的问题。