不能腌制<class 'module.class'>不是同一个物体

问题描述 投票:0回答:0

虽然这个问题有几个答案,但没有一个对我有用。

我有一个 cython 项目,其中包含一个执行多线程的类。

cythonMod.pyx:

class doThreadingStuff(Process):
    KillIt = False
    def __init__(self, to_emitter: Pipe, queue_from_mother: Queue, queue_to_mother: Queue, daemon=True):
        super().__init__()

    def run(self):
        threading.Thread(target=wasupbrah, daemon=True, name="wasupbrah",
                                     args=(self.queue_to_mother,self.queue_from_mother, text,)).start()

def wasupbrah(queue_to_mother, queue_from_mother):
    print("[+] called wasupbrah")
    # do stuff

cdef public void mainCode():
    print("Running MainCode() here")
    if ctypes.windll.shell32.IsUserAnAdmin():
        #do PyQt Stuff
        app = QtWidgets.QApplication(sys.argv)

        mother_pipe, child_pipe = Pipe()
        queue_to_mother = Queue()
        queue_from_mother = Queue()
        emitter = QtDesignerStuff.Emitter(mother_pipe, queue_to_mother, queue_from_mother)

        dThS = doThreadingStuff(child_pipe, queue_from_mother, queue_to_mother)
        dThS.start()

不幸的是,我无法提供完整的代码,但我提供了我认为有问题的部分。

如果您使用 cython 在上面进行编译,它将生成一个

cythonMod.pyd
cythonMod.c
cythonMod.h
,以及使
mainCode
函数成为公共声明,可供外部 C 代码访问。

如果我移动

mainCode
runcythonMod.py
并以
python runcythonMod.py
运行它,它会完美运行。

现在,我有一个 C 程序,它简单地调用 cython 项目中的

mainCode
函数,如下所示:

runcythonMod.c:

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <stdio.h>
#include "runcythonMod.h"
#include "nanalyzer.h"

//compile using: gcc -o runcythonMod.exe cythonMod.c cythonMod.c -IC:\Users\username\AppData\Local\Programs\Python\Python39\include -IC:\Users\username\AppData\Local\Programs\Python\Python39\include -LC:\Users\username\AppData\Local\Programs\Python\Python39\libs -lpython39
int main(){
    printf("current PID %d\n", getpid());
    PyImport_AppendInittab("mainCode", PyInit_cythonMod);
    Py_Initialize();
    //PySys_SetPath("C:/Users/username/AppData/Local/Programs/Python/python39/;.");

    PyObject *sys = PyImport_ImportModule("sys");
    PyObject *path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyUnicode_FromString("."));
    PyList_Append(path, PyUnicode_FromString("C:/Users/username/AppData/Local/Programs/Python/python39/"));


    /* 1st: Import the module */
    PyObject* ModuleString = PyUnicode_FromString((char*) "commonmodules");
    if (!ModuleString) {
        PyErr_Print();
        printf("Error formating python script\n");
    }

    PyObject* Module = PyImport_Import(ModuleString);
    if (!Module) {
        PyErr_Print();
        printf("Error importing python script\n");
    }


    /* 2nd: Getting reference to the function */
    PyObject* Function = PyObject_GetAttrString(Module, (char*)"mainCode");
    if (!Function) {
        PyErr_Print();
        printf("Pass valid argument to mainCode()\n");
    }

    printf("Good So far!\n");

    if(PyImport_ImportModule("mainCode") == NULL){
        printf("Failed to import mainCode\n");
    }
    __pyx_f_13cythonMod_mainCode();
    return 0;
}

问题我认为泡菜抱怨

doThreadingStuff
是从
mainCode
函数调用的,而不是从我的C的
main
函数调用的。不幸的是,很难从我的 C 代码中调用
doThreadingStuff
,因为我的 cython 有一个 PyQt5 进程并在 PyQt5 应用程序和
doThreadingStuff
之间共享管道和队列。

我尝试按照网络的建议创建一个单独的函数来调用

doThreadingStuff
,但这也没有用。

  File "C:\Users\username\AppData\Local\Programs\Python\Python39\Lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
  File "C:\Users\username\AppData\Local\Programs\Python\Python39\Lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\username\AppData\Local\Programs\Python\Python39\Lib\multiprocessing\context.py", line 327, in _Popen
    return Popen(process_obj)
  File "C:\Users\username\AppData\Local\Programs\Python\Python39\Lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\username\AppData\Local\Programs\Python\Python39\Lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <class 'cythonMod.doThreadingStuff'>: it's not the same object as cythonMod.doThreadingStuff
def pickledoThreadingStuff(child_pipe, queue_from_mother, queue_to_mother):
    dThS = doThreadingStuff(child_pipe, queue_from_mother, queue_to_mother)
    dThS.start()


cdef public void mainCode():
    print("Running MainCode() here")
    if ctypes.windll.shell32.IsUserAnAdmin():
        #do PyQt Stuff
        app = QtWidgets.QApplication(sys.argv)

        mother_pipe, child_pipe = Pipe()
        queue_to_mother = Queue()
        queue_from_mother = Queue()
        emitter = QtDesignerStuff.Emitter(mother_pipe, queue_to_mother, queue_from_mother)

        pickledoThreadingStuff(child_pipe, queue_from_mother, queue_to_mother)

以上也没有用。

非常感谢所有回复。

c multithreading pyqt5 cython pickle
© www.soinside.com 2019 - 2024. All rights reserved.