Как параметризовать смешанные классы в Python? - PullRequest
0 голосов
/ 12 июня 2019

Я разрабатываю абстрактный класс BaseServer:

class BaseServer(abc.ABC):

    @abc.abstractmethod
    def serve(self):
        raise NotImplementedError

    @abc.abstractmethod
    def shutdown(self):
        raise NotImplementedError

    @abc.abstractmethod
    def send(self, *args, **kwargs):
        raise NotImplementedError

    @abc.abstractmethod
    def finalise(self, *args, **kwargs):
        raise NotImplementedError

    @abc.abstractmethod
    def is_serving(self):
        raise NotImplementedError

    def set_handler(self, handler):
        self.__handler = handler

    def _handle(self, *args, **kwargs):
        try:
            self.__handler.handle(self, *args, **kwargs)
        except AttributeError:
            pass

    def _cleanup(self):
        pass

, а также классы ThreadPoolMixin и ProcessPoolMixin mixin (по мотивам модуля socketserver Python):

class ThreadPoolMixin:

    def _handle(self, *args, **kwargs):
        try:
            future = self.__pool.submit(super()._handle, *args, **kwargs)
            self.__futures.append(future)
        except AttributeError:
            self.__pool = concurrent.futures.ThreadPoolExecutor(1)
            self.__futures = []
            future = self.__pool.submit(super()._handle, *args, **kwargs)
            self.__futures.append(future)

    def _cleanup(self):
        try:
            for future in self.__futures:
                future.cancel()

            self.__pool.shutdown()
        except AttributeError:
            pass


class ProcessPoolMixin:

    def _handle(self, *args, **kwargs):
        try:
            future = self.__pool.submit(super()._handle, *args, **kwargs)
            self.__futures.append(future)
        except AttributeError:
            self.__pool = concurrent.futures.ProcessPoolExecutor(1)
            self.__futures = []
            future = self.__pool.submit(super()._handle, *args, **kwargs)
            self.__futures.append(future)

    def _cleanup(self):
        try:
            for future in self.__futures:
                future.cancel()

            self.__pool.shutdown()
        except AttributeError:
            pass

    def __getstate__(self):
        class Temp:
            pass

        state = self.__dict__.copy()
        temp = Temp()
        temp.__dict__ = state

        try:
            del temp.__pool
            del temp.__futures
        except AttributeError:
            pass

        return temp.__dict__

Эти классы позволяют мне создавать конкретные подклассы в соответствии с моими потребностями:

class HTTPServer(BaseServer):
    pass


class AMQPServer(BaseServer):
    pass


class ThreadingHTTPServer(ThreadPoolMixin, BaseServer):
    pass


class ThreadingAMQPServer(ThreadPoolMixin, BaseServer):
    pass


class ProcessingHTTPServer(ProcessPoolMixin, BaseServer):
    pass


class ProcessingAMQPServer(ProcessPoolMixin, BaseServer):
    pass

Как я могу настроить размер пула потоков и размер пула процессов из этих подклассов?

1 Ответ

1 голос
/ 13 июня 2019

Я нашел решение: используя атрибут public class , как в socketserver.ThreadingMixIn и socketserver.ForkingMixIn.

class ThreadPoolMixin:

    pool_size = 1

    def _handle(self, *args, **kwargs):
        try:
            future = self.__pool.submit(super()._handle, *args, **kwargs)
            self.__futures.append(future)
        except AttributeError:
            self.__pool = concurrent.futures.ThreadPoolExecutor(
                self.pool_size)
            self.__futures = []
            future = self.__pool.submit(super()._handle, *args, **kwargs)
            self.__futures.append(future)

    def _cleanup(self):
        try:
            for future in self.__futures:
                future.cancel()

            self.__pool.shutdown()
        except AttributeError:
            pass


class ThreadingHTTPServer(ThreadPoolMixin, BaseServer):

    pool_size = 4


class ThreadingAMQPServer(ThreadPoolMixin, BaseServer):

    pool_size = 2
...