I am creating a class to set, hold and access data throughout the project. Below is my Data class:
class Data:
"""This class stores project-related constants as class attributes for easy access throughout the project."""
ORG_URL: str = "https://www.myurl.com/"
PROJECT_NAME: str = "My Project"
root_path: str = ""
@classmethod
def set_root_path(cls, new_path):
cls.root_path = new_path
Below is my Main class which sets the root when run:
from multiprocessing import Process, Manager
class Main:
def __init__(self) -> None:
# determine if application is a script file or frozen exe
if getattr(sys, 'frozen', False):
application_path = os.path.dirname(sys.executable)
elif __file__:
application_path = os.path.dirname(__file__)
data = Data()
data.set_root_path(f"{application_path}")
with Manager() as manager:
q = manager.Queue()
args = manager.Queue()
print(data.root_path) ## prints correct path
gui = Process(target=GUI,args=(q,args,data))
runner = Process(target=Runner,args=(q,args,data))
gui.start()
runner.start()
gui.join()
runner.join()
if __name__ == "__main__":
Main()
Below is my Runner class where i am accessing the root_path:
class Runner:
def __init__(self,q,args,data) -> None:
print("Initiating Runner")
self.q = q
self.args = args
self.data = data
print(self.data.root_path) # prints ''
I tried multiple things but could not resolve it. Please help.
This is because processes are spawned in Windows (and MacOS by default), not forked. As a result modules are reloaded when a new process is spawned, so module-level class
statements are re-executed, and so are the initialization of class variables within.
To transfer an object across processes you should use an instance of a class rather than a class. For readability you can create a dataclass
instead so the instance attributes can be declared in as clean a way as class variables:
from dataclasses import dataclass
@dataclass
class Data:
ORG_URL: str = "https://www.myurl.com/"
PROJECT_NAME: str = "My Project"
root_path: str = ""
def set_root_path(self, new_path):
self.root_path = new_path
Demo (run under Linux in explictly spawn mode): https://replit.com/@blhsing1/RequiredDisguisedCodewarrior