python装饰器函数执行后日志_python使用装饰器@函数式化django开发

django是一个python web开发的框架。作为一个框架MVC的架构已经实现起来了。但是编码的时候你经常要进行进一步的抽象。

AOP是一种称为面向切面的开发思想,意思是将部分功能代码在运行时动态的加载到指定位置。最常见的应用是Spring中的依赖注入@Autowired。

而装饰器也可以被看成是一种AOP的实现,但是又有些许的不同,让我们来体会一下。

在我们的实例中我们将django中的views.py(其实是controller层)拆出了implement.py(实现)和decorator.py(装饰器)

1、先看我们的views.py。

这里我们只给出一个接口做为演示。# -*- coding:utf-8 -*-

import json

import logging

import implement

import decorator

from django.views.decorators.csrf import csrf_exempt

logger = logging.getLogger(__name__)

@csrf_exempt

@decorator.impl_wrapper_check_time

@decorator.process_time

@decorator.cache

def alarm_month_daytotal(request):

if request.method == 'GET':

time_str = request.GET.get('time')

return implement.alarm_month_daytotal(time_str)

alarm_total接口在views.py中的函数alarm_total中并没有返回JSONResponse对象,而是直接返回了调用implement.alarm_total()的结果,看样子是implement.alarm_total()返回了JSONResponse

,我们看看是不是这样。

2、implement实现层# -*- coding:utf-8 -*-

import json

import logging

import calendar

from rediss import RedisCache

from config import redis_config, alarm_status_mapping, alarm_type_mapping, alarm_level_mapping, combine_module, alarm_module_mapping,alarm_stage_mapping, \

alarm_type_config_mapping, month_total_closed_mapping, month_total_tosolve_mapping

from datetime import datetime, timedelta

from dao import Dao as dash_dao

from exceptions import DataEmptyException

import time

logger = logging.getLogger(__name__)

# 按月获取分天报警情况

def alarm_month_daytotal(time_str):

time_object = datetime.strptime(time_str, '%Y-%m')

month, length = calendar.monthrange(time_object.year, time_object.month)

ret_list = [0 for i in range(length)]

items = dash_dao.get_alarms_by_month(time_str)

if not items:

raise DataEmptyException('[table] %s' % 'alarm_list_table')

for item in items:

if not item.alarm_time:

continue

ret_list[at_day(item.alarm_time) - 1] += 1

r = RedisCache(redis_config)

key_list = r.keys("dmonitor:issue:%s*" % time_str)

if not key_list:

return ret_list

for key in key_list:

content = r.get(key)

time_object = datetime.strptime(key.split(':')[2], '%Y-%m-%d')

ret_list[time_object.day - 1] = {

'y': ret_list[time_object.day - 1],

'name': content,

'marker': {

'symbol': 'url(/data_monitor/static/images/sun.png)'

}

}

return ret_list

并没有啊,implement.alarm_total()只返回了一个list对象。这是为什么呢?

原因就在那几个装饰器的封装上。

3、装饰器decorator

impl_wrapper_check_time(func):执行装饰的装饰的func方法,并且对返回进行JSONResponse封装

process_time(func):统计执行时间并打印日志

cache(func):对接口的请求加入缓存

执行顺序,装饰器装饰的顺序,从下往上我们例子里是cache->process_time->impl_wrapper_check_time那么:

1、先执行impl_wrapper_check_time的开始部分

2、然后是process_time时间的start_time记录

3、cache缓存的准备

4、被装饰的函数func

5、cache缓存的返回

6、process_time的end_time记录,并打印时间日志

7、impl_wrapper_check_time返回JSONResponse

执行顺序说明:

1、异常也是按照这个顺序一级一级的向上抛出。

2、最终由impl_wrapper_check_time处理异常,返回errno:0或者-1。

3、先执行完缓存的返回,再执行时间的统计,这样可以明显观察到缓存对处理时间性能上的提升。import logging

import time

import json

import traceback

from rediss import RedisCache

from config import redis_config, cache_timeout, cache_switch

from exceptions import IllegalParamException

from django.http import JsonResponse

from django.http import HttpResponse

logger = logging.getLogger(__name__)

redis = RedisCache(redis_config)def impl_wrapper_check_time(func):

def wrapper(*args, **kwargs):

try:

if args[0].method == 'GET':

if not args[0].GET.get('time'):

raise IllegalParamException('time')

data = func(*args, **kwargs)

return JsonResponse({'errno': 0, 'msg': 'success', 'data': data})

except Exception, ex:

logger.error(traceback.format_exc())

return JsonResponse({'errno': -1, 'msg': str(ex)})

return wrapper

def process_time(func):

def wrapper(*args, **kwargs):

path = args[0].get_full_path()

start_time = time.time()

data = func(*args, **kwargs)

end_time = time.time()

logger.info('path: %s, process_time: %s ms' % (path, str((end_time - start_time) * 1000)))

return data

return wrapper

def cache(func):

def wrapper(*args, **kwargs):

if not cache_switch:

data = func(*args, **kwargs)

return data

path = args[0].get_full_path()

dashboard_cache_key = 'dashboard:cache:%s' % path

if redis.get(dashboard_cache_key):

logger.info('[Hit Cache] path: %s' % path)

return json.loads(redis.get(dashboard_cache_key))

data = func(*args, **kwargs)

redis.set(dashboard_cache_key, json.dumps(data))

redis.expire(dashboard_cache_key, cache_timeout)

logger.info('[Query] path: %s' % path)

return data

return wrapper

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值