Create a subprocess from a function belonging to a class that stores an object that cannot be pickled

19 views Asked by At

Im trying to create a little 2D game engine using Unicurses. To do so, I have created a Player base class, which handles all the keystrokes and communicates them to the main program via a pipe. To get the keystrokes I use the unicurses.wgetch(screen) function, which requires a reference to the screen created by the unicurses.initscr() function. This reference however is a ctypes.c_void_p, which cant be pickled, and thus raises an exeption when i try to create a subprocess (using the multiprocessing module) executing the main function of the Player class.

Here an example code that produces the exact same error while somewhat keeping the structure of my program

import multiprocessing as mp
import unicurses as curses
from typing import Type
from multiprocessing.connection import PipeConnection
class playerbase():
    def __init__(self) -> None:
        #do something
        ...
        
    def _handshake(self, pipe:PipeConnection):
        self.pipe = pipe

    def init(self, screen):
        self.scr = screen
        #do other things
    def start(self):
        key = curses.wgetch(scr_id=self.scr)
        #do something
class engine():
    def __init__(self, player: Type[playerbase] = playerbase):
        self.player = player()
    def mainloop(self):   #gets called by the main program to start the rendering and stuff
        In, Out = mp.Pipe()
        self.player._handshake(Out)
        self.loop(In, self.player)   #I originally intended to make this a subprocess
    def loop(self, pipe:PipeConnection, player):
        stdscr = curses.initscr()
        player.init(stdscr)
        PProc = mp.Process(target=player.start, args=())
        PProc.start()

def main():
    e = engine()
    e.mainloop()
if __name__ == "__main__":
    main()

This produces the following error:

Traceback (most recent call last):
  File "[FILEPATH]", line 38, in <module>
    main()
  File "[FILEPATH]", line 36, in main
    e.mainloop()
  File "[FILEPATH]", line 26, in mainloop
    self.loop(In, self.player)   #I originally intended to make this a subprocess
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "[FILEPATH]", line 32, in loop
    PProc.start()
  File "C:\Users\[USER]\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
                  ^^^^^^^^^^^^^^^^^
  File "C:\Users\[USER]\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\[USER]\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\context.py", line 336, in _Popen
    return Popen(process_obj)
           ^^^^^^^^^^^^^^^^^^
  File "C:\Users\[USER]\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\popen_spawn_win32.py", line 94, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\[USER]\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
ValueError: ctypes objects containing pointers cannot be pickled
0

There are 0 answers