如何使用装饰器记录来自特定模块的所有函数调用?

时间:2017-07-27 17:21:01

标签: python arcpy

某些背景:

我正在尝试编写一个用于记录的装饰器。具体来说,我与arcpy合作很多,从工具中获取消息的方法是使用arcpy.GetMessages()。但是,这是一种烦人的功能,因为它只保存最新的消息,并且必须在每个工具之后调用。伪代码示例

import arcpy
import logging
log = logging.getLogger(__name__)

def test_function(in_data):
    out_data = 'C:/new_path/out_data'
    arcpy.MakeFeatureLayer_management(in_data, out_data)
    log.info(arcpy.GetMessages())

    arcpy.Delete_management(in_data)
    log.info(arcpy.GetMessages()) 

    # If you did log.info(arcpy.GetMessages()) again here you'd just get 
    # the message from the Delete tool again

编写一个可以识别调用arcpy函数的任何时间并记录它的装饰器会好得多。像:

def log_the_arcpy(fn):
    @functools.wraps(fn)
    def inner(*args, **kwargs):
        result = fn(*args, **kwargs)
        # Some magic happens here?!
        if module_parent == arcpy: #module_parent is obviously fake, is there a real attribute?
            log.info(arcpy.GetMessages())
        return result
    return inner

但是,我完全陷入两个地方:(1)如何识别单个功能的“arcpy-ness”(或任何包),以及(2)总体方法使用装饰器挖掘函数内部并确定潜在的许多函数调用的包成员资格。

似乎有用的比特是:

这些都没有得到很好的充实 - 这是因为其中许多主题对我来说都是新鲜事。我会很感激任何方向 - 我想尽早提问,所以我以后不会被问到一堆XY Problem questions

2 个答案:

答案 0 :(得分:1)

如果你要直接在arcpy上调用方法,那么包装模块可能是最简单且性能影响最小的方法:

# arcpy_proxy.py
import arcpy as _arcpy
import logging

class _proxy(object):

    def __getattr__(self, item):
        ref = getattr(_arcpy, item)
        if callable(ref):  # wrap only function calls
            return self._wrap(ref)
        return ref

    @classmethod
    def _wrap(cls, func):
        def inner(*args, **kwargs):
            val = func(*args, **kwargs)
            logging.info(_arcpy.GetMessages())  # log the messages
            return val
        return inner

arcpy = _proxy()

然后你可以from arcpy_proxy import arcpy作为替补。您甚至可以在主脚本中添加sys.modules["arcpy"] = arcpy(在导入课程后),这样您就不必在其他任何地方替换它来代理它。

答案 1 :(得分:0)

这应该有效:

void increment(int *num) {
    *num = *num + 1;
}

int main() {
    int num = 0;
    for (int i = 0; i < 100; i++) {
        increment(&num);
    }
    printf("%d\n", num); // this prints 100
}

全功能:

if hasattr(fn, '__module__') and getattr(fn, '__module__') == 'arcpy':
    log.info(arcpy.GetMessages())