python 优化代码时,按行自动解析耗时

文章展示了如何使用Python编写一个缓存装饰器,该装饰器利用Redis存储函数结果并处理过期时间。同时,文章还引入了cProfile和line_profiler库来分析代码的执行时间和堆栈使用情况,以优化性能。
import logging
import os
import sys
from functools import wraps
import pickle
from dynaconf import settings
from common.redis_client import redis_client as redis
from common.utils import get_object_size
from termcolor import cprint
from cProfile import Profile
from pstats import Stats
from line_profiler import LineProfiler


REDIS_PREFIX = os.environ.get('REDIS_PREFIX', 'xdata_offline')
USE_REDIS_CACHE = os.environ.get("USE_REDIS_CACHE", 'true')
DEFAULT_EXPIRE_SECOND = int(os.environ.get("DEFAULT_EXPIRE_SECOND", 600))

logging.debug(f'--decorator--REDIS_PREFIX:{REDIS_PREFIX}, USE_REDIS_CACHE:{USE_REDIS_CACHE}')


def cache(ex: int = DEFAULT_EXPIRE_SECOND):
    """
    Args:
        ex: Defaults to 300 seconds; Never expire when less than or equal to 0
    """
    def redis_cache(func):
        tmp_redis_key = f"{REDIS_PREFIX}@webserver@{func.__module__}_{func.__name__}"

        def generate_redis_key(*args, **kwargs):
            # not contains defaults kwargs
            return f"{tmp_redis_key}_{str(args)}_{str(kwargs)}"

        key_set = f"{tmp_redis_key}_set"

        @wraps(func)
        def wrap(*args, **kwargs):
            if USE_REDIS_CACHE != 'true':
                return func(*args, **kwargs)
            
            key = generate_redis_key(*args, **kwargs)
            
            res = redis.get(key)
            if res:
                logging.debug(f'success get value from redis key:{key} ttl:{redis.ttl(key)}s')
                try:
                    return pickle.loads(res)
                except Exception as e:
                    logging.exception('pickle load exceptin')

            res = func(*args, **kwargs)

            if settings.ENV_FOR_DYNACONF != "DEVELOPMENT":
                pickle_res = pickle.dumps(res)
                # TODO: add other type: list/hash/sordset
                if ex <= 0:
                    redis.set(key, pickle_res)
                else:
                    redis.set(key, pickle_res, ex=ex)
                logging.debug(f'success set redis key:{key}, ex:{ex}, size:{get_object_size(pickle_res)}')
                redis.sadd(key_set, key)
            return res
        
        def clear_cache():
            redis_keys = redis.smembers(key_set)
            if redis_keys:
                logging.debug(f'need clear redis_keys:{redis_keys}')
                redis.delete(*redis_keys)
                redis.delete(key_set)
        
        wrap.clear_cache = clear_cache
        # wrap.generate_redis_key = generate_redis_key
        # wrap.key_set = key_set

        return wrap

    return redis_cache


def code_stack_used_time_parse(func):
    @wraps(func)
    def wrap(*args, **kwargs):
        pro = Profile()
        cprint(f"start run:{func.__name__}".center(30, "="), "green")
        res = pro.runcall(func, *args, **kwargs)
        stats = Stats(pro)
        stats.strip_dirs()
        stats.sort_stats('cumulative')
        stats.print_stats(10)
        return res
    return wrap


def line_used_time_parse(func):
    @wraps(func)
    def wrap(*args, **kwargs):
        profile = LineProfiler(func)
        profile.enable()
        cprint(f"start run:{func.__name__}".center(30, "="), "green")
        res = func(*args, **kwargs)
        profile.disable()
        profile.print_stats(sys.stdout, output_unit=1e-3)
        return res
    return wrap

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值