为每次调用外部API

时间:2017-09-06 13:51:38

标签: python django python-2.7

我有一个无法修改的外部API。对于每次调用此API,我需要能够在之前和之后执行操作。此API使用如下:

def get_api():
    """
    Return an initiated ClassAPI object
    """
    token = Token.objects.last()
    api = ClassAPI(
        settings.CLASS_API_ID,
        settings.CLASS_API_SECRET,
        last_token)

    return api
在代码中的任何地方都会调用

get_api(),然后将结果用于执行请求(例如:api.book_store.get(id=book_id))。 我的目标是返回一个虚拟对象,它将执行与ClassAPI添加打印相同的操作"之前"并打印"之后"。

ClassAPI看起来像这样:

class ClassAPI
    class BookStore
        def get(...)
        def list(...)

    class PenStore
        def get(...)
        def list(...)

我尝试创建一个继承自(ClassApi, object) [因为ClassAPI并不继承自object]的类,并在此类中添加一个装饰所有方法的元类,但是我无法影响BookStore(获取和列表)

中的方法

有关如何仅修改get_api()并添加其他类的任何想法?我尽量避免复制API的整个结构来添加我的操作。

我正在使用python 2.7。

1 个答案:

答案 0 :(得分:1)

您可以使用代理执行此操作:

class Proxy:
    def __init__(self, other):
        self.other = other
        self.calls = []

    def __getattr__(self, name):
        self.calls.append(name)
        return self

    def __call__(self, *args, **kwargs):
        self.before()
        ret = self.call_proxied(*args, **kwargs)
        self.after()
        return ret

    def call_proxied(self, *args, **kwargs):
        other = self.other
        calls = self.calls
        self.calls = []
        for item in calls:
            other = getattr(other, item)
        return other(*args, **kwargs)

此类拦截__getattr__()方法中的未知成员,保存使用的名称并返回自身。

当一个方法被调用时(例如api.book_store.get(id=book_id)),它会在自身上调用before()after()方法,并在它之间获取other和前进的成员通话中的参数。

您可以像这样使用此类:

def get_api():
    ...
    return Proxy(api)

更新:更正了对self.call_proxied(*args, **kwargs)的通话。还允许返回任何返回值。