如何在Spyne服务器方法中使用'self'参数

3 投票
1 回答
1279 浏览
提问于 2025-04-18 17:16

我在很多Spyne的例子中看到,所有的方法都没有通常的self参数,也没有使用cls。它们使用的是ctx参数,但ctx既不是指实例,也不是指类(而且我需要保持一些状态)。

这样做可以吗?还是说这些类并没有被实例化,而是作为静态类使用?

我试图做一些类似于:

# -*- coding: utf-8 -*-

from __future__ import (
    absolute_import,
    unicode_literals,
    print_function,
    division
)

from spyne.decorator import rpc
from spyne.service import ServiceBase
from spyne.model.primitive import String


class RadianteRPC(ServiceBase):
    def __init__(self, name):
        self._name = name

    @rpc(_returns=String)
    def whoami(self):
        """
        Dummy test method.
        """
        return "Hello I am " + self._name + "!"

这段代码的问题在于,RadianteRPC似乎从来没有被Spyne当作对象实例化,而是作为静态类使用。

解决方案 1:目前来看,Spyne并不实例化任何对象。因此,如果我们需要存储一些状态,可以通过类属性来实现。

因为我们在方法中无法访问cls参数,所以我们需要通过类名来引用类,这样我们可以做一些类似于:

class RadianteRPC(ServiceBase):
    _name = "Example"

    @rpc(_returns=String)
    def whoami(ctx):  # ctx is the 'context' parameter used by Spyne
        """
        Dummy test method.
        """
        return "Hello I am " + RadianteRPC._name + "!"

解决方案 2(在Spyne邮件列表中找到):

在很多情况下,我们可能无法直接引用类名,所以我们还有另一个选择:通过ctx参数找到类。

class RadianteRPC(ServiceBase):
    _name = "Example"

    @rpc(_returns=String)
    def whoami(ctx):  # ctx is the 'context' parameter used by Spyne
        """
        Dummy test method.
        """
        return "Hello I am " + ctx.descriptor.service_class._name + "!"

1 个回答

1

我做的事情是创建了一个应用程序类的子类,然后通过 ctx.app 来访问应用程序对象。

from spyne.protocol.soap.soap11 import Soap11
from spyne.server.wsgi import WsgiApplication
from spyne import Application, rpc, ServiceBase, Unicode, Boolean

class MyApplication(Application):
    def __init__(self, *args, **kargs):
        Application.__init__(self, *args, **kargs)
        assert not hasattr(self, 'session')
        self.session = 1

    def increment_session(self):
        self.session += 1

    def get_session(self):
        return self.session

class Service(ServiceBase):
    @rpc(_returns=Integer)
    def increment_session(ctx):
        s = ctx.app.get_session()
        self.increment_session()
        return s

application = MyApplication([MatlabAdapterService],
                        'spyne.soap',
                        in_protocol=Soap11(validator='lxml'),
                        out_protocol=Soap11())
wsgi_application = WsgiApplication(application)
...

我觉得应该有一种更“干净”的方法——不需要去创建应用程序类的子类,而是可以创建上下文的子类,但这样做应该可以让你动态地工作。

回到你的问题,你也可以访问你的服务,因为这个服务是在 Application.services 属性中定义的。

撰写回答