I am working on a side projects which involves creating a separate process for flask server on demand.
I have already tried using dill function pickling but so far no luck and used al the techniques mentioned here AttributeError: Can't pickle local object in Multiprocessing
Here is the code for the same: ApiServer.py
import pickle
import ProcessBuilder as pb
import ServiceLogger as sl
import SystemRecovery as sr
from flask import Flask, Response
from waitress import serve
from flask_cors import CORS
class EndpointAction(object):
def __init__(self, action):
self.action = action
self.logger = sl.ServiceLogger()
self.response = Response(status=200, headers={})
def __call__(self, *args):
self.action()
return self.response
class ApiServer:
def __init__(self):
self.server = None
self.debug = sr.Recovery().debug
self.port = sr.Recovery().api_port
self.host = '127.0.0.1'
self.logger = sl.ServiceLogger()
self.app = Flask(__name__)
CORS(self.app, resources={r"/api/*": {"origins": "*"}})
self.register_endpoints()
self.server = pb.ProcessBuilder().create_process(self.run, [self])
def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None):
self.app.add_url_rule(endpoint, endpoint_name, EndpointAction(handler))
def register_endpoints(self):
return None
def start(self):
self.server.start()
def run(self):
print("heyy")
#serve(self.app, port=self.port, host=self.host)
def terminate(self):
self.server.kill()
return None
a = ApiServer()
a.start()
print("heyy")
a.terminate()
print("thread killed")
ProcessBuilder.py
from multiprocessing import Process
import random
import string
import dill
import ServiceLogger as sl
class DillProcess(Process):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._target = dill.dumps(self._target) # Save the target function as bytes, using dill
def run(self):
if self._target:
self._target = dill.loads(self._target) # Unpickle the target function before executing
self._target(*self._args, **self._kwargs) # Execute the target function
class ProcessBuilder:
def __init__(self):
self.processes = []
self.logger = sl.ServiceLogger()
def create_process(self, method, args=[]):
process = DillProcess(name=self.__generate_instance_name(), target=method, args=tuple(args))
self.processes.append(process)
return process
def get_process_instance(self, process_name):
for process in self.processes:
if str(process.name) == process_name:
return process
return None
def run_process(self, process):
process.start()
def kill_process(self, process):
process.kill()
def __generate_instance_name(self):
# printing lowercase
letters = string.ascii_lowercase
randomString = ''.join(random.choice(letters) for i in range(3))
# printing letters
letters = string.digits
randomDigits = ''.join(random.choice(letters) for i in range(5))
return randomString + "" + randomDigits
Error:
Traceback (most recent call last):
File "C:\Users\..", line 55, in <module>
a.start()
File "C:\Users\..", line 43, in start
self.server.start()
File "C:\Python\Lib\multiprocessing\process.py", line 121, in start
self._popen = self._Popen(self)
^^^^^^^^^^^^^^^^^
File "C:\Python\Lib\multiprocessing\context.py", line 224, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python\Lib\multiprocessing\context.py", line 336, in _Popen
return Popen(process_obj)
^^^^^^^^^^^^^^^^^^
File "C:\Python\Lib\multiprocessing\popen_spawn_win32.py", line 94, in __init__
reduction.dump(process_obj, to_child)
File "C:\Python\Lib\multiprocessing\reduction.py", line 60, in dump
ForkingPickler(file, protocol).dump(obj)
AttributeError: Can't pickle local object 'Flask.__init__.<locals>.<lambda>'