首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python中的单例模式问题

python中的单例模式问题
EN

Stack Overflow用户
提问于 2022-05-25 15:51:23
回答 1查看 357关注 0票数 0

我使用带有单例模式的python类来获得不同类型的好处,例如

  • 限制对共享资源的并发访问。
  • 用于为资源创建全局访问点;
  • 用于创建类的一个实例,贯穿程序的整个生命周期。

但是现在也有一些问题,所以让我知道如何解决这个问题,但得到了上面提到的单例模式的好处。注意:这里的使用python进行SOAP调用。

示例代码:

代码语言:javascript
复制
from zeep.plugins import HistoryPlugin
from shared import Singleton
import zeep

class MySoapClient(metaclass=Singleton):
    """MyFancySoapClient"""

    def __init__(
        self,
        user: str = "username",
        password: str = "password",
        wsdl: str = "wsdl_url_goes_here",
    ):
        self._history = HistoryPlugin()
        self._soap_client = zeep.Client(wsdl, plugins=[self._history])



    def methodA():
        resp = self._soap_client.ServiceA(
            body
        )
        return resp
    
    def methodB():
        resp = self._soap_client.ServiceB(
            body
        )
        return resp

    def methodC(request_proxy_url):
        self._soap_client.transport.session.proxies = {"https": request_proxy_url}
        resp = self._soap_client.ServiceE(
            body
        )
        return resp
    
    def methodD():
        resp = self._soap_client.ServiceC(
            body
        )
        return resp

    def methodE():
        resp = self._soap_client.ServiceD(
            body
        )
        return resp

client = MySoapClient()
client.methodA()
client.methodB()
client.methodC("https://example.com")  <---- after this call it modifies the '_soap_client' attribute
client.methodD()  
client.methodE()

这就是为什么methodD()methodE()由于添加了self._soap_client.transport.session.proxies而受到影响的原因,实际上,我只需要为methodC()设置代理URL,但是由于单例,它还将更新的属性值传播到mothodD()methodE()。最后,使我的methodD()methodE()失败,因为这些方法中的SOAP调用不需要用于代理。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-25 17:35:13

您可以将methodC重写为:

代码语言:javascript
复制
    def methodC(request_proxy_url):
        original_proxies = self._soap_client.transport.session.proxies
        self._soap_client.transport.session.proxies = {"https": request_proxy_url}
        resp = self._soap_client.ServiceE(
            body
        )
        self._soap_client.transport.session.proxies = original_proxies
        return resp

(对于在发出请求之前需要修改self._soap_client实例设置的任何其他方法,请执行类似的操作)

我对执行单例模式有点怀疑,而不只是在模块中创建全局变量并从任何地方导入.但这只是个人品味,与你的问题无关。

我认为,了解SOAP的本质,zeep.Client实例是一个相当沉重的对象,因此,如果您能够避免使用多个实例,那么尝试避免多个实例是完全有意义的。

如果您使用多线程平台(例如,使用gevent的Python ),那么您必须小心避免全局vars改变它们的共享状态,就像MySoapClient现在所做的那样。

另一种方法是维护少量不同的zeep.Client实例,并为每个methodA、methodC等使用适当的_soap_client实例。类似于:

代码语言:javascript
复制
class MySoapClient(metaclass=Singleton):
    """MyFancySoapClient"""

    def __init__(
        self,
        user: str = "username",
        password: str = "password",
        wsdl: str = "wsdl_url_goes_here",
        request_proxy_url: str = "default value",
    ):
        self._history = HistoryPlugin()
        self._soap_client = zeep.Client(wsdl, plugins=[self._history])
        self._soap_client_proxied = zeep.Client(wsdl, plugins=[self._history])
        self._soap_client_proxied.transport.session.proxies = {"https": request_proxy_url}

    def methodB():
        resp = self._soap_client.ServiceB(
            body
        )
        return resp

    def methodC(request_proxy_url):
request_proxy_url}
        resp = self._soap_client_proxied.ServiceE(
            body
        )
        return resp

   # etc
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72380753

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档