简体   繁体   English

Python - 嵌套类 Singleton

[英]Python - Nested Singleton Classes

Is it possible to nest an arbitrary number Singleton classes within a Singleton class in Python?是否可以在 Python 中的 Singleton class 中嵌套任意数量的 Singleton 类?

There's no problem in changing my approach to solving this issue if a simpler alternative exists.如果存在更简单的替代方法,则改变我解决此问题的方法没有问题。 I am just using the "tools in my toolset", if you will.如果您愿意,我只是在使用“我的工具集中的工具”。 I'm simulating some larger processes so bear with me if it seems a bit far-fetched.我正在模拟一些更大的过程,所以如果它看起来有点牵强,请多多包涵。

An arbitrary number of gRPC servers can be started up and each server will be listening on a different port.可以启动任意数量的 gRPC 服务器,每个服务器将在不同的端口上侦听。 So for a client to communicate with these servers, separate channels and thus separate stubs will need to be created for a client to communicate to a given server.因此,为了让客户端与这些服务器进行通信,需要为客户端创建单独的通道并因此创建单独的存根以与给定服务器进行通信。

You could just create a new channel and a new stub every time a client needs to make a request to a server, but I am trying to incorporate some best practices and reuse the channels and stubs.每次客户端需要向服务器发出请求时,您都可以创建一个新通道和一个新存根,但我正在尝试合并一些最佳实践并重用通道和存根。 My idea is to create a Singleton class that is comprised of Singleton subclasses that house a channel and stub pair as instance attributes.我的想法是创建一个 Singleton class,它由 Singleton 个子类组成,其中包含通道和存根对作为实例属性。 I would have to build the enclosing class in a way that allows me to add additional subclasses whenever needed, but I have never seen this type of thing done before.我将不得不构建封闭的 class 以允许我在需要时添加其他子类的方式,但我以前从未见过这种类型的事情。

The advantage to this approach is that any module that instantiates the main Singleton class will have access to the existing state of the channel and stub pairs, without having to recreate anything.这种方法的优点是任何实例化主要 Singleton class 的模块都可以访问现有的 state 通道和存根对,而无需重新创建任何东西。

I should note that I already initialize channels and stubs from within Singleton classes and can reuse them with no problem.我应该注意到,我已经从 Singleton 类中初始化了通道和存根,并且可以毫无问题地重用它们。 But the main goal here is to create a data structure that allows me to reuse/share a variable amount of gRPC channel and stub pairs.但这里的主要目标是创建一个数据结构,允许我重用/共享可变数量的 gRPC 通道和存根对。

The following is code for reusing the gRPC Channel object;下面是复用gRPC Channel object的代码; the stubs are built in a very similar way, only difference is they accept the channel as an arguement.存根以非常相似的方式构建,唯一的区别是它们接受通道作为参数。

class gRPCChannel(object):
    _instance, _channel = None, None
    port: int = 50051

    def __new__(cls):
        """Subsequent calls to instance() return the singleton without repeating the initialization step"""
        if cls._instance is None:
            cls._instance = super(gRPCChannel, cls).__new__(cls)
            # The following is any initialization that needs to happen for the channel object
            cls._channel = grpc.insecure_channel(f'localhost:{cls.port}', options=(('grpc.enable_http_proxy', 0),))
        return cls._channel

    def __exit__(self, cls):
        cls._channel.close()

I think this is simpler than the "singleton pattern":我认为这比“单例模式”更简单:

# grpc.py
import functools as ft

class GrpcChannel:
    pass  # normal class, no funny __new__ overload business


@ft.lru_cache
def channel():
    return GrpcChannel()

Usage:用法:

import grpc

channel = grpc.channel()
assert grpc.channel() is channel

If you really want it all namespaced under the class (IMO no reason to, takes more typing & syntax for no extra benefit), then:如果你真的希望它全部命名空间在 class 下(IMO 没有理由,需要更多的输入和语法没有额外的好处),那么:

class GrpcChannel:
    @classmethod
    @ft.lru_cache
    def instance(cls):
        return cls()

# usage
assert grpc.GrpcChannel.instance() is grpc.GrpcChannel.instance()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM