2016-12-08 66 views
0

我對python相當陌生,我試圖編寫一個簡單的REST API調用實現。我的目標是能夠在運行時創建類的方法,並能夠使用方法名稱作爲API調用的基礎。例如list_virtual_networks會變成GET到http://localhost:8080/virtual-networks等。我也想練習一些更高級的面向對象技術。這裏是我的方法:在python運行時創建方法

def _api_call_wrapper(wrapped_function): 
    def wrapper_function(*args, **kwargs): 
     handler_name = wrapped_function.__name__ 
     agent_logger.info('Got function name {}'.format(handler_name)) 
     <do something> 
     return res 
return wrapper_function 

class API(HTTPConnection): 
    def __init__(self, host, port): 
     <do something> 

    def __getattr__(self, name): 
    @_api_call_wrapper 
    def handler(self, *args, **kwargs): 
     self.request('GET', self.last_url) 
     return self.getresponse() 
    handler.__name__ = name 
    setattr(self, name, handler) 
    agent_logger.info('Returning method with name {}'.format(self.name)) 

if __name__ == '__main__': 
    api = API(127.0.0.1, 8080) 
    api.list_virtual_networks() 

這裏就是我在日誌中看到:

2016年12月8日23:05:03034 - AgentLogger - 信息 - 在0x1073c8d70>

返回法名稱功能wrapper_function 2016-12-08 23:05:03,034 - AgentLogger - INFO - 返回方法名稱無

我希望自己清楚地解釋我想實現的目標。有沒有辦法通過我試圖做到的方式至少粗略地解決它?

+1

你正在嘗試一些相當新的python的難題 – turbulencetoo

+0

你真的想做什麼?你確定在飛行中創建方法對於你想要做的事情是必要的嗎? –

+0

對於目前我正在嘗試解決的問題,這不是100%必需的。當然,我可以手動定義所有的API調用方法,也可以只定義一個通用的方法,它可以在其輸入中獲取URL方法和HTTP方法的類型,併發送REST調用。我認爲這更加「科學」的興趣促使我以這種方式實施它。在我看來,它可能是一個非常靈活的實現,我以後也可以重用。 –

回答

0

當寫功能的包裝,使用一個很好的工具是由Python的STDLIB提供的functoolswraps功能:https://docs.python.org/3/library/functools.html#functools.wraps(尤其是你想做的「重命名」的東西)

from functools import wraps 

def _api_call_wrapper(wrapped_function): 
    @wraps(wrapped_function) 
    def wrapper_function(*args, **kwargs): 
     handler_name = wrapped_function.__name__ 
     agent_logger.info('Got function name {}'.format(handler_name)) 
     <do something> 
     return res 
return wrapper_function 
+0

我可以使用的模塊集非常有限,因爲這個腳本將在我沒有控制的服務器上運行,並且我不能在那裏安裝我的選擇模塊,必須使用已經存在的模塊。不過謝謝你的回覆,我會試試這個。 –

+0

實際上,'functools'庫不必安裝,因爲它在Python 2/3的Python stdlib中存在,所以只要你使用python,你已經*已*安裝了這個模塊;) – KokaKiwi

+0

Thank您。我在回答之前的評論後不久也發現了這一點。 –

0

我發現這是一個解決方案。我加了一個裝飾,用來重命名功能

def _function_rename(new_name): 
    def decorator(f): 
    f.__name__ = new_name 
    return f 

return decorator 

然後我將此裝飾給處理函數,除了裝飾在__getattr__定義,我已經申請:

def __getattr__(self, name): 
    @_api_call_wrapper 
    @_function_rename(name) 
    def handler(*args, **kwargs): 
     self.request(*args, **kwargs) 
     return self.getresponse() 

    return handler 

現在,當一個沒有在類中定義的方法被調用,它被分配一個在處理函數中定義的裝飾代碼。