2010-09-22 60 views
0

我正在写通过XMLRPC接口到维基中类(代码简化如下):包裹的xmlrpclib Python的方式调用类似multicalls

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方法,如果没有涉及认证,或者如果有身份验证,则将其包装在多层中。例如:

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

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) 
+0

不工作。 fooMethod()是一个远程方法,不存在于xmlrpclib.MultiCall类中(您会得到一个AttributeError)。该类的实例将处理任意方法名称,因为它们只是传递给远程端,但仍然使我处于像问题中所述的_getMultiCall()之类的解决方案。 – Luke404 2010-09-23 05:16:50

+0

更新答案,使其与使队列函数调用的MultiCall对象一起工作。 – 2010-09-23 13:32:01