Search code examples
pythonpython-3.xvisual-studio-codemultiprocessingpyttsx3

Python multiprocessing Process cant pickle pyttsx3.init()


Im currently working on a TTS application with multiprocessing and pyttsx3. If i try to start a process and pass the pyttsx3.init("sapi5") object as an argument in order to use it to speak in the target function it returns a TypeError because of pickling and a PermissionError. Here is a reproduction example:

import pyttsx3

def dummy(engine):
    engine.say("test")
    engine.runAndWait()

if __name__ == "__main__":
    multiprocessing.Process(target=dummy, args=(pyttsx3.init("sapi5"),)).start()

and the error that is produced:

D:/Python3.9.2_x64/python.exe "d:/VSCode Projects/TTS/test2.py"
Traceback (most recent call last):
  File "d:\VSCode Projects\TTS\test2.py", line 9, in <module>
    multiprocessing.Process(target=dummy, args=(pyttsx3.init("sapi5"),)).start()
  File "D:\Python3.9.2_x64\lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
  File "D:\Python3.9.2_x64\lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "D:\Python3.9.2_x64\lib\multiprocessing\context.py", line 327, in _Popen
    return Popen(process_obj)
  File "D:\Python3.9.2_x64\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
    reduction.dump(process_obj, to_child)
  File "D:\Python3.9.2_x64\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle 'module' object

D:\VSCode Projects>Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "D:\Python3.9.2_x64\lib\multiprocessing\spawn.py", line 107, in spawn_main
    new_handle = reduction.duplicate(pipe_handle,
  File "D:\Python3.9.2_x64\lib\multiprocessing\reduction.py", line 79, in duplicate
    return _winapi.DuplicateHandle(
PermissionError: [WinError 5] Zugriff verweigert

Note: "Zugriff verweigert" is "Access denied" in english

PS: This is my first question here so feel free to give feedback


Solution

  • "If i try to start a process and pass the pyttsx3.init("sapi5") object as an argument in order to use it to speak in the target function it returns a TypeError because of pickling" Correct, because the object can't be pickled. What is pickling? Pickling is, roughly speaking, serialization of data in Python. Why do we need pickling for multiprocessing? Because Python has something called a global interpreter lock which means that in order to have multiprocessing, Python needs to spawn new processes with their own interpreters. And to share data with those processes, the data has to be serialized. What this all boils down to is, until you understand pickling of objects, just stick to only passing builtin types as arguments to multiprocessing functions. Don't try and pass something complicated like pyttsx3.init("sapi5") because yea, it probably won't pickle.

    (I don't know what the permissions thing is about but I'll stick to answering the title of the question. Open a separate question if that persists).