Python Fehler bei Multiprocessing?
Hallo,
Momentan schreibe ich eine kleine Anwendung die Text sprechen soll. Mein Code:
Voice.py
from loguru import logger
import pyttsx3
import multiprocessing
class Voice():
def __init__(self):
import YAML
self.process = None
logger.debug("[CONFIG] Reading Config Data")
self.voiceId = YAML.config['assistant']['Voice']['VoiceID']
logger.debug("[Start] Voice initialistion")
self.engine = pyttsx3.init()
self.engine.setProperty('voice', self.voiceId)
logger.debug("[Finish] Voice initialistion")
def __speak__(self, text):
self.engine.say(text)
self.engine.runAndWait()
def say(self, text):
if self.process:
self.stop()
logger.debug("[START] Say process")
p = multiprocessing.Process(target=self.__speak__, args=(text, ))
p.start()
self.process = p
def stop(self):
if self.process:
self.process.terminate()
logger.info("[STOPP] Say process")
Main.py
from loguru import logger
import Voice
logger.info("[START] ...")
self.Voice = Voice.Voice()
logger.info("...")
self.Voice.say("Initalisierung abgeschloßen")
Bei der Ausführung wird mir aber folgender Fehler ausgegeben:
Traceback (most recent call last):
File "C:\Users\toni-\Desktop\VoiceAssistant\main.py", line 15, in <module>
Assistant = VoiceAssistant()
^^^^^^^^^^^^^^^^
File "C:\Users\toni-\Desktop\VoiceAssistant\main.py", line 9, in __init__
self.Voice.say("Initalisierung abgeschloßen")
File "C:\Users\toni-\Desktop\VoiceAssistant\Voice.py", line 26, in say
p.start()
File "C:\Users\toni-\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
^^^^^^^^^^^^^^^^^
File "C:\Users\toni-\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\toni-\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\context.py", line 336, in _Popen
return Popen(process_obj)
^^^^^^^^^^^^^^^^^^
File "C:\Users\toni-\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\popen_spawn_win32.py", line 94, in __init__
reduction.dump(process_obj, to_child)
File "C:\Users\toni-\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
TypeError: cannot pickle 'module' object
PS C:\Users\toni-\Desktop\VoiceAssistant> Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\toni-\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 106, in spawn_main
source_process = _winapi.OpenProcess(
^^^^^^^^^^^^^^^^^^^^
OSError: [WinError 87] Falscher Parameter
Wie startest du das ganze?
Ich verwende meine Klasse, zuerst erstelle ich eine Instanz davon danach verwende ich die say Funktion.
Die Frage war eher, ob Du eien IDE nutzt, oder das direkt von der Kommandozeile aus startest.
ich starte mit CMD
2 Antworten
Du importierst yaml im Konstruktor der Klasse, sodaß das Modul Teil der Objektinstanz wird. Soll nun die Klasse gepickled werden, dann müßte auch yaml einem pickling unterzogen werden.
Die Fehlermeldung:
TypeError: cannot pickle 'module' object
besagt das Objekte vom Typ module nicht picklebar sind.
In dieser Zeile:
p = multiprocessing.Process(target=self.__speak__, args=(text, ))
gibst du an, dass die __speak__-Methode in einem anderen Prozess ausgeführt werden soll. Folglich muss auch das gesamte daranhängende Objekt (bzw. die Voice-Instanz) in diesen anderen Prozess verschoben werden.
Das geschieht üblicherweise über eine zwischenzeitliche Objektserialisierung mittels des pickle-Moduls. Da du aber im Stacktrace die Meldung:
TypeError: cannot pickle 'module' object
erhältst, muss man wohl davon ausgehen, dass dieser Vorgang fehlgeschlagen ist.
Ich würde vermuten, dass das engine-Property nicht serialisiert werden kann. Das kannst du ja auch einmal gegenprüfen.
Sofern ich damit richtig liege, wäre es wohl besser, das engine-Property erst innerhalb von __speak__ zu definieren.