• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    Python import模块的缓存问题解决方案

    在使用django开发的平台中,支持用户自定义函数,但是每次用户进行修改编辑后,该模块内容已更改,然后重新导入该模块,但是Python 会认为“我已经导入了该模块,不需要再次读取该文件”,所以更改将无效。

    因此,每次更改文件的内容时,都必须退出并重新启动Django。

    使用python开发后台服务程序的时候,每次修改代码之后都需要重启服务才能生效比较麻烦

    要解决这个问题,有以下几种方式:

    最简单、最有效的方法:重新启动 Django。但是,这也有缺点,特别是丢失了 django名称空间中存在的数据以及其他导入模块中的数据。

    对于简单的情况,可以使用 Python 的​reload()​函数。在许多情况下,在编辑一个模块之后使用

    ​reload()​函数就足够满足需求。

    这里主要是介绍第二种方式:

    ​reload()​是 Python 提供的内置函数,在不同的 Python 版本中有不同的表现形式:

    在 Python 2.x 中,reload()是内置函数。

    在 Python 3.0 - 3.3 中,可以使用imp.reload(module)。

    在 Python 3.4 中,imp 已经被废弃,取而代之的是importlib。

    Python2.7可以直接用reload():

    python2 内置函数reload(module)

    Python3可以用下面几种方法:

    方法一:基本方法

    from imp import reload
    reload(module)

    方法二:

    import imp
    imp.reload(module)

    方法三:

    import importlib
    importlib.reload(module)

    方法四:

    from importlib import reload
    reload(module)

    说明:

    module 必须是已经成功导入的模块

    模块被加载到内存以后,更改文件内容,已经运行的程序不会生效的,可通过reload重新加载。

    导入是一个开销很大的操作。

    python中缓存模块的一些用法

    一.问题描述

    有时候可能需要缓存一些 成员方法的值, 可能成员方法的计算比较耗时,有时候不希望重复调用计算该值, 这个时候就可以缓存该值.

    查了一下标准库 有 functools.lru_cache 有一个 lru_cache 可以缓存成员函数的值,

    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    """
    @author: Frank 
    @contact: frank.chang@shoufuyou.com
    @file: test_lru_cache.py
    @time: 2018/9/8 下午8:55
    """
    import time
    from functools import lru_cache
    
    class Model:
        @lru_cache(maxsize=10)
        def calculate(self, number):
            print(f'calculate({number}) is  running,', end=' ')
            print('sleep  3s  ')
            time.sleep(3)
            return number * 3
    
    if __name__ == '__main__':
    
        model = Model()
    
        for i in range(5):
            print(model.calculate(i))
    
        for i in range(5):
            print(model.calculate(i))

    结果如下:

    calculate(0) is  running, sleep  3s 
    0
    calculate(1) is  running, sleep  3s 
    3
    calculate(2) is  running, sleep  3s 
    6
    calculate(3) is  running, sleep  3s 
    9
    calculate(4) is  running, sleep  3s 
    12
    0
    3
    6
    9
    12

    从结果开出来, 第二次计算的时候 , 就没有计算 而是通过缓存取值, 所以成员方法只计算了一次.

    lru_cache 可以指定 max_size 缓存的大小, typed bool 如果为True, 代表不同类型分别缓存. 如果达到max_size 淘汰策略是LRU, LRU是Least Recently Used的缩写,即最近最少使用,常用于页面置换算法.

    二 第三方的模块

    第三方的模块cachetools 已经提供了很多缓存策略,直接拿来用一下.

    来看下面的例子.

    1 来看一个缓存成员方法例子

    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    """
    @author: Frank 
    @contact: frank.chang@shoufuyou.com
    @file: test_cache.py
    @time: 2018/9/8 下午12:59
    pip install cachetools
    
    https://docs.python.org/3/library/operator.html
    
    缓存成员方法的值 
    cachetools  已经实现好了, 直接用就可以了. 
    
    """
    from operator import attrgetter
    import time
    from cachetools import LRUCache,RRCache , cachedmethod
    
    class Model:
        def __init__(self, cachesize):
            self.cache = LRUCache(maxsize=cachesize)
    
        @cachedmethod(attrgetter('cache'))
        def get_double_num(self, num):
            """ return  2* num"""
            print(f'get_double_num({num})  is running')
            time.sleep(2)
            return num * 2
    
    model = Model(cachesize=10)
    print(model.get_double_num(10))
    print(model.get_double_num(10))
    print(model.get_double_num(10))
    print(model.get_double_num(10))
    print(model.get_double_num(10))
    print(model.get_double_num(10))

    结果如下:

    get_double_num(10)  is running
    20
    20
    20
    20
    20
    20
    Process finished with exit code 0

    可以看出, 值计算一次 函数,第二次走的是缓存. 非常好用. 在初始化方法里面构造一个缓存对象, 之后用 cachedmethod 修饰成员函数,同时 用attrgetter(‘cache') 把cache 拿到就可以用了.

    实际上 cachetools 实现了很多缓存策略,具体缓存策略可以参考下面的链接.

    'Cache', 'LFUCache',
    'LRUCache',
    'RRCache', 'TTLCache',

    ‘cached', ‘cachedmethod' 这两个分别用来修饰 函数和成员方法的.

    2 来看一个 缓存函数

    # 缓存 函数的值
    from cachetools import cached
    @cached(cache={})
    def fib(n):
        print((f'fib({n}) is  running.'))
        return n if n  2 else fib(n - 1) + fib(n - 2)
    
    for i in range(20):
        print('fib(%d) = %d' % (i, fib(i)))
    @cached(cache={})
    def fun(n):
        print(f'fun({n}) is runnnig.')
        time.sleep(3)
        return n ** 2
    
    if __name__ == '__main__':
        for _ in range(5):
            print(fun(4))
    

    如果cache = None , 表示不缓存,该计算结果.

    结果如下:

    fun(4) is runnnig.
    16
    16
    16
    16
    16

    直接导入 cached 里面 传入一个字典就可以了,用起来也比较方便.

    实现分析:

    缓存思路大致是一样的, 首先先把参数hash 一下生成一个key, 然后看key 是否在自己的缓存里,不在就计算方法(函数),之后把key和对应value 放到自己的子弟那里面. 如果下一次计算该值,生成一个key 看是否在 自己的字典里面,如果在直接返回即可. 当然这是基本的思路, 里面还有用到 缓存淘汰策略, 多线程是否要加锁,等比较复杂的问题.

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

    您可能感兴趣的文章:
    • Python入门基础之import机制
    • 解决Python import .pyd 可能遇到路径的问题
    • python 指定源路径来解决import问题的操作
    • 关于Python3的import问题(pycharm可以运行命令行import错误)
    • 解决python3.x安装numpy成功但import出错的问题
    • python import 上级目录的导入
    上一篇:关于Python的pymouse click 双击的问题
    下一篇:python之np.argmax()及对axis=0或者1的理解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    Python import模块的缓存问题解决方案 Python,import,模块,的,缓存,