pythonic方法将xmlrpclib调用包装在类似的multical中

时间:2010-09-22 17:17:37

标签: python class methods

我正在编写一个通过xmlrpc连接到MoinMoin wiki的类(简化代码如下):

class MoinMoin(object):
    token = None

    def __init__(self, url, username=None, password=None):
        self.wiki  = xmlrpclib.ServerProxy(url + '/?action=xmlrpc2')
        if username and password:
            self.token = self.wiki.getAuthToken(username, password)
    # some sample methods:
    def searchPages(self, regexp):
    def getPage(self, page):
    def putPage(self, page):

现在,如果没有涉及身份验证,我的每个方法都需要单独调用相关的xmlrpc方法,或者如果有auth则将其包装在multicall中。例如:

def getPage(self, page):
    if not self.token:
        result = self.wiki.getPage(page)
    else:
        mc = xmlrpclib.MultiCall(self.wiki) # build an XML-RPC multicall
        mc.applyAuthToken(self.token)       # call 1
        mc.getPage(page)                    # call 2
        result = mc()[-1]                  # run both, keep result of the latter
    return result

除了为每种方法重复这些东西之外,有没有更好的方法呢?

因为我必须调用任意方法,用东西包装它们,然后在另一个类上调用同名方法,选择相关结果并将它们还给我,我怀疑解决方案会涉及元类或类似的深奥(对我来说)东西。我应该看看xmlrpclib源代码,看看它是如何完成的,然后可能将它们的MultiCall子类化为我的东西...

但也许我错过了一些更容易的东西。我提出的最好的是:

def _getMultiCall(self):
    mc = xmlrpclib.MultiCall(self.wiki)
    if self.token:
        mc.applyAuthToken(self.token)
    return mc
def fooMethod(self, x):
    mc = self._getMultiCall()
    mc.fooMethod(x)
    return mc()[-1]

但它仍然为我需要实现的每个方法重复相同的三行代码,只需更改被调用的方法名称。还好吗?

1 个答案:

答案 0 :(得分:1)

Python函数是对象,因此可以很容易地将它们传递给其他函数。

def HandleAuthAndReturnResult(self, method, arg):
    mc = xmlrpclib.MultiCall(self.wiki)
    if self.token:
        mc.applyAuthToken(self.token)
    method(mc, arg)
    return mc()[-1]
def fooMethod(self, x):
    HandleAuthAndReturnResult(xmlrpclib.MultiCall.fooMethod, x)

可能有其他方式,但我认为它应该有效。当然,arg部分需要与方法所需的一致,但所有方法都需要一个参数。

编辑:我不明白MultiCall是一个代理对象。即使真正的方法调用最终是您的ServerProxy中的那个,也不应该传递此方法对象,以防MultiCall覆盖(定义)它。在这种情况下,您可以使用 getattribute 方法和要调用的方法名称,然后调用返回的函数对象。注意处理AttributeError异常。

现在的方法如下:

def HandleAuthAndReturnResult(self, methodName, arg):
    mc = xmlrpclib.MultiCall(self.wiki)
    if self.token:
        mc.applyAuthToken(self.token)

    try:
        methodToCall = getattr(mc, methodName)
    except AttributeError:
        return None

    methodToCall(arg)
    return mc()[-1]

def fooMethod(self, x):
    HandleAuthAndReturnResult('fooMethod', x)